diff --git a/js/trdom_servermanager.js b/js/trdom_servermanager.js index b4bef39..8a0867c 100644 --- a/js/trdom_servermanager.js +++ b/js/trdom_servermanager.js @@ -15,12 +15,24 @@ class trdom_servermanager extends EventTarget { } #registerServer = function(name, initdata) { - let server = new trserver(initdata, function(msg) {this.#logcb(`server:${name}`, 6, msg);}.bind(this)); + let server = new trserver(name, initdata, function(msg) {this.#logcb(`server:${name}`, 6, msg);}.bind(this)); this.#servers[name] = server; - server.addEventListener('torrent-update', this); + //server.addEventListener('torrent-update', this); + let e = new CustomEvent('torrentserver-added', { + detail: { + serverName: name, + serverObject: server + } + }); + this.dispatchEvent(e); server.refreshTorrentList(); } + addServer(name, url, user, pass) { + this.#registerServer(name, {'rpcurl': url, 'auth': `Basic ${btoa(`${user}:${pass}`)}`}); + this.#saveServers(); + } + #loadcb; #loadServers() { let serverjson = this.#loadcb('servers'); @@ -53,28 +65,36 @@ class trdom_servermanager extends EventTarget { this.#saveServers(); } - constructor (loadcb = null, savecb = null, logcb = null, registerServer = null) { + constructor (loadcb = null, savecb = null, logcb = null) { super(); this.#loadcb = loadcb; this.#savecb = savecb; this.#logcb = logcb - - //this.#registerServer = registerServer; - - //this.#servers = this.#loadServers(); } handleEvent(e) { this.#log(6, `Handling event of type ${e.type}`); switch (e.type) { - case 'torrent-update': + // add controls and listener for server events to new trtorrent + case 'torrent-created': + let hash = e.detail.torrentHash + let torrent = e.detail.torrentObject; + for (const [srv, server] of Object.entries(this.#servers)) { + let control = new trdom_torrentcontrol(hash, server, (srv == e.detail.serverName) ? e.detail.torrentInfo : null, this.#logcb); + torrent.addControl(srv, control); + } + this.addEventListener('torrentserver-added', e.detail.torrentObject); + break; + //TODO: nuke, don't relay + /*case 'torrent-update': for (const [srv, server] of Object.entries(this.#servers)) { if (e.target == server) { let newEvent = new CustomEvent('torrent-update', { - 'detail': { - 'torrentHash': e.detail.torrentHash, - 'torrentInfo': e.detail.torrentInfo, - 'serverName': srv + detail: { + torrentHash: e.detail.torrentHash, + torrentInfo: e.detail.torrentInfo, + serverName: srv, + serverObject: server } }); this.dispatchEvent(newEvent); @@ -82,7 +102,7 @@ class trdom_servermanager extends EventTarget { } } this.#log(2, `Got update event for unknown server:\n${JSON.stringify(e.detail)}`); - break; + break;*/ default: this.#log(5, `Event type ${e.type} not supported`); break; diff --git a/js/trdom_torrentcontrol.js b/js/trdom_torrentcontrol.js index 3f92669..15379eb 100644 --- a/js/trdom_torrentcontrol.js +++ b/js/trdom_torrentcontrol.js @@ -1,6 +1,6 @@ "use strict"; -class trdom_torrentcontrol { +class trdom_torrentcontrol extends EventTarget { #logcb; #log(loglevel, msg) { if (this.#logcb !== null) { @@ -16,8 +16,74 @@ class trdom_torrentcontrol { #hash; #server; - //TODO: remove - #getKnownTorrents; + #updateDOM(data) { + let control_element = this.#element; + let status = control_element.element_status; + + control_element.classList.remove( + 'trweb_status_asdf', + 'trweb_status_offline', + 'trweb_status_nonexistent', + 'trweb_status_paused', + 'trweb_status_verifqueued', + 'trweb_status_verifying', + 'trweb_status_downloading', + 'trweb_status_seeding' + ); + + nukeChildren(status); + + let statustext = 'Nothing to see here'; + let statusclass = 'trweb_status_asdf' + let barwidth = 50; + if (!this.#server.isOnline()) { + statustext = "Server offline"; + statusclass = 'trweb_status_offline'; + barwidth = 0; + } + else { + let server_status = data; + if (server_status == undefined || server_status.deleted) { + statustext = "Not available"; + statusclass = 'trweb_status_nonexistent'; + barwidth = 0; + } + else { + statustext = `${server_status.status}`; + barwidth = server_status.percentDone; + switch (server_status.status) { + case 0: + statustext = 'Paused'; + statusclass = 'trweb_status_paused'; + break; + case 1: + statustext = 'Queued for verification'; + statusclass = 'trweb_status_verifqueued'; + break; + case 2: + statustext = 'Verifying'; + statusclass = 'trweb_status_verifying'; + break; + case 3: + statustext = 'Queued'; + break; + case 4: + statustext = 'Downloading'; + statusclass = 'trweb_status_downloading'; + break; + case 6: + statustext = 'Seeding'; + statusclass = 'trweb_status_seeding'; + break; + } + + statustext = `[${this.#server.name}]: ${statustext} - ${server_status.percentDone}%`; + } + } + control_element.element_statusbar.style.width = `${barwidth}%`; + control_element.classList.add(statusclass); + status.appendChild(document.createTextNode(statustext)); + } handleEvent(e) { switch (e.type) { @@ -33,7 +99,7 @@ class trdom_torrentcontrol { e.stopPropagation(); break; case 'magnet': - let magneturl; + /*let magneturl; for (const [srv, data] of Object.entries(this.#getKnownTorrents()[this.#hash].servers)) { if (data.magnetLink != null) { magneturl = data.magnetLink; @@ -45,8 +111,9 @@ class trdom_torrentcontrol { } else { this.#log(3, `Couldn't find magnet link! ${JSON.stringify(this.#getKnownTorrents()[this.#hash].servers)}`); - } + }*/ e.stopPropagation(); + window.alert('not implemented'); break; case 'download': e.stopPropagation(); @@ -54,14 +121,20 @@ class trdom_torrentcontrol { break; } } + break; + case 'torrent-update': + if (e.detail.torrentHash == this.#hash) { + this.#updateDOM(e.detail.torrentInfo); + } + break; } } - constructor(hash, server, logcb, getKnownTorrents) { + constructor(hash, server, initdata = null, logcb = null) { + super(); this.#hash = hash; this.#server = server; this.#logcb = logcb; - this.#getKnownTorrents = getKnownTorrents; let srv = server.name; @@ -130,6 +203,12 @@ class trdom_torrentcontrol { this.#element.element_pause = element_pause; this.#element.element_magnet = element_magnet; this.#element.element_download = element_download; + + if (initdata != null) { + this.#updateDOM(initdata); + } + + server.addEventListener('torrent-update', this); } } \ No newline at end of file diff --git a/js/trdom_torrentmanager.js b/js/trdom_torrentmanager.js index 7311581..83b2bce 100644 --- a/js/trdom_torrentmanager.js +++ b/js/trdom_torrentmanager.js @@ -1,12 +1,63 @@ "use strict"; -class trdom_torrentmanager { +class trdom_torrentmanager extends EventTarget { + #logcb; + #log(loglevel, msg) { + if (this.#logcb !== null) { + this.#logcb('trdom_torrentmanager', loglevel, msg); + } + } + #element = document.createElement('div'); getElement() { return this.#element; } - constructor() { + #torrentDB = {}; + get torrents() { + return this.#torrentDB; + } + + constructor(logcb = null) { + super(); + this.#logcb = logcb; this.#element.classList.add('trweb_torrentlistview', 'container-fluid'); } + + handleEvent(e) { + this.#log(6, `Handling event of type ${e.type}`); + switch (e.type) { + // if we get info of a torrent that we don't have in the DB, create it, + // then alert trdom_servermanager so it can add server controls to it + // that'll also handle alerting trtorrents of new servers + case 'torrent-update': + let hash = e.detail.torrentHash; + if (this.#torrentDB[hash] == null) { + let torrent = new trtorrent(hash); + this.#torrentDB[hash] = torrent; + this.#element.appendChild(torrent.element); + this.dispatchEvent(new CustomEvent( + 'torrent-created', + { + detail: { + torrentHash: hash, + torrentObject: torrent, + torrentInfo: e.detail.torrentInfo, + serverName: e.detail.serverName, + serverObject: e.detail.serverObject + } + } + )); + } + break; + case 'torrentserver-added': + let server = e.detail.serverObject; + // see this handler + server.addEventListener('torrent-update', this); + break; + default: + this.#log(5, `Event type ${e.type} not supported`); + break; + } + } } diff --git a/js/trserver.js b/js/trserver.js index cd7e4b9..ffd09a8 100644 --- a/js/trserver.js +++ b/js/trserver.js @@ -1,26 +1,47 @@ "use strict"; class trserver extends EventTarget { + #name; + get name() { + return this.#name; + } #rpcurl; #authHeader; #sessionHeader; #requests = []; #torrents = {}; #isOnline = false; + #setOnline(online) { + if (this.isOnline == online) { + return; + } + this.#isOnline = online; + let detail = { + }; + let etype; + if (online) { + etype = 'torrentserver-online'; + } + else { + etype = 'torrentserver-offline'; + } + this.dispatchEvent(new CustomEvent(etype, detail)); + } #logger = function(msg) {}; #torrentCallback = function(hash, torrentInfo) { let e = new CustomEvent('torrent-update', { - 'detail': { - 'torrentHash': hash, - 'torrentInfo': torrentInfo + detail: { + torrentHash: hash, + torrentInfo: torrentInfo } }); this.dispatchEvent(e); }; - constructor (initdata, logger = null, tcb = null) { + constructor (name, initdata, logger = null, tcb = null) { super(); + this.#name = name; this.#rpcurl = initdata.rpcurl; if (logger != null) { this.#logger = logger; diff --git a/js/trtorrent.js b/js/trtorrent.js index 7fa71db..6c9ceae 100644 --- a/js/trtorrent.js +++ b/js/trtorrent.js @@ -2,20 +2,20 @@ class trtorrent { #element = document.createElement('div'); - getElement() { + get element() { return this.#element; } #hash; #name = '## NAME NOT SET ##'; - #element_server = {}; + #serverControls = {}; addControl(srv, control) { - this.#element_server[srv] = control; + this.#serverControls[srv] = control; this.#element.appendChild(control.getElement()); } getControl(srv) { - return this.#element_server[srv]; + return this.#serverControls[srv]; } #servers = {}; diff --git a/js/trweb.js b/js/trweb.js index 12260fe..55311a0 100644 --- a/js/trweb.js +++ b/js/trweb.js @@ -13,6 +13,11 @@ class trweb { this.#logger(`${module}: ${msg}`); } }.bind(this); + #log(loglevel, msg) { + if (this.#logcb !== null) { + this.#logcb('TRWEB', loglevel, msg); + } + } #timer; @@ -22,7 +27,7 @@ class trweb { #dom_menubar = new trdom_menubar(); #dom_servermanager; - #dom_torrentmanagger = new trdom_torrentmanager(); + #dom_torrentmanagger; constructor (container, loadcb, savecb, logger) { this.#container = container; @@ -34,9 +39,18 @@ class trweb { this.#logger = logger; } - this.#dom_servermanager = new trdom_servermanager(this.#loadcb, this.#savecb, this.#logcb, this.#registerServer); + this.#dom_servermanager = new trdom_servermanager(this.#loadcb, this.#savecb, this.#logcb); + this.#dom_torrentmanagger = new trdom_torrentmanager(this.#logcb); - this.#dom_servermanager.addEventListener('torrent-update', this); + //TODO: these should be handled by trdom_torrentmanager + //this.#dom_servermanager.addEventListener('torrent-update', this); + //this.#dom_servermanager.addEventListener('torrentserver-added', this); + + //this.#dom_servermanager.addEventListener('torrent-update', this.#dom_torrentmanagger);// for creating torrents when we first get their info + + /* trdom_torrentmanager uses this to add its listeners onto servers */ + this.#dom_servermanager.addEventListener('torrentserver-added', this.#dom_torrentmanagger); + this.#dom_torrentmanagger.addEventListener('torrent-created', this.#dom_servermanager);// for adding server controls to new torrents this.#guiFooter = document.createElement('div'); this.#guiFooter.classList.add('trweb_footer'); @@ -52,45 +66,8 @@ class trweb { } } - #registerServer = function(name, initdata) { - let torrentCallback = function(hash, torrentInfo) { - let mergedTorrentInfo = this.#knownTorrents[hash]; - if (mergedTorrentInfo == null) { - mergedTorrentInfo = this.#createTorrentEntry(hash); - } - mergedTorrentInfo.setStatus(name, torrentInfo); - mergedTorrentInfo.name = torrentInfo.name; - - this.#updateTorrentDisplay(mergedTorrentInfo); - }.bind(this); - let newserver = new trserver(initdata, function(msg) {this.#logger(`[Server: ${name}]: ${msg}`);}.bind(this), torrentCallback); - this.#dom_servermanager.getServers()[name] = newserver; - newserver.refreshTorrentList(); - }.bind(this); - #createTorrentEntry(hash) { - let torrent = new trtorrent(hash); - - this.#knownTorrents[hash] = torrent; - - for (const srv of Object.keys(this.#dom_servermanager.getServers())) { - this.#createServerEntryForTorrent(hash, srv); - } - - this.#dom_torrentmanagger.getElement().appendChild(torrent.getElement()); - this.#updateTorrentDisplay(torrent); - - return torrent; - } - - #createServerEntryForTorrent(hash, srv) { - this.#needsSort = true; - let control = new trdom_torrentcontrol(hash, this.#dom_servermanager.getServers()[srv], this.#logcb, function() {return this.#knownTorrents}.bind(this)); - - let torrent = this.#knownTorrents[hash]; - - torrent.addControl(srv, control); } #updateTorrentDisplay(torrent) { @@ -170,30 +147,34 @@ class trweb { } handleEvent(e) { + this.#log(6, `Handling event of type ${e.type}`); switch (e.type) { - case 'DOMContentLoaded': - this.#logger('Activating TRWEB instance'); - - this.#container = document.getElementById(this.#container); - this.#container.classList.add('trweb_container'); - this.#container.appendChild(this.#dom_menubar.getElement()); - this.#container.appendChild(this.#dom_torrentmanagger.getElement()); - this.#container.appendChild(this.#guiFooter); - - this.#dom_servermanager.loadServers(); - this.#dom_servermanager.saveServers(); - this.setTimer(); - break; - case 'torrent-update': - let mergedTorrentInfo = this.#knownTorrents[e.detail.torrentHash]; - if (mergedTorrentInfo == null) { - mergedTorrentInfo = this.#createTorrentEntry(e.detail.torrentHash); - } - mergedTorrentInfo.setStatus(e.detail.serverName, e.detail.torrentInfo); - mergedTorrentInfo.name = e.detail.torrentInfo.name; + case 'DOMContentLoaded': + this.#logger('Activating TRWEB instance'); + + this.#container = document.getElementById(this.#container); + this.#container.classList.add('trweb_container'); + this.#container.appendChild(this.#dom_menubar.getElement()); + this.#container.appendChild(this.#dom_torrentmanagger.getElement()); + this.#container.appendChild(this.#guiFooter); + + this.#dom_servermanager.loadServers(); + //this.#dom_servermanager.saveServers(); + this.setTimer(); + break; + case 'torrent-update': + let mergedTorrentInfo = this.#knownTorrents[e.detail.torrentHash]; + if (mergedTorrentInfo == null) { + mergedTorrentInfo = this.#createTorrentEntry(e.detail.torrentHash); + } + mergedTorrentInfo.setStatus(e.detail.serverName, e.detail.torrentInfo); + mergedTorrentInfo.name = e.detail.torrentInfo.name; - this.#updateTorrentDisplay(mergedTorrentInfo); - break; + this.#updateTorrentDisplay(mergedTorrentInfo); + break; + default: + this.#log(5, `Event type ${e.type} not supported`); + break; } } @@ -239,13 +220,7 @@ class trweb { } addServer(name, url, user, pass) { - this.#registerServer(name, {'rpcurl': url, 'auth': `Basic ${btoa(`${user}:${pass}`)}`}); - - for (const hash of Object.keys(this.#knownTorrents)) { - this.#createServerEntryForTorrent(hash, name); - } - - this.#dom_servermanager.saveServers(); + this.#dom_servermanager.addServer(name, url, user, pass); } removeServer(name) {