/// class FileEntry { } class FileListRequest { } class DownloadFileTransfer { constructor(handle, id) { this.currentSize = 0; this.on_start = () => { }; this.on_complete = () => { }; this.on_fail = (_) => { }; this.on_data = (_) => { }; this.transferId = id; this._handle = handle; } startTransfer() { if (!this.remoteHost || !this.remotePort || !this.transferKey || !this.totalSize) { this.on_fail("Missing data!"); return; } console.debug("Create new file download to " + this.remoteHost + ":" + this.remotePort + " (Key: " + this.transferKey + ", Expect " + this.totalSize + " bytes)"); this._active = true; this._socket = new WebSocket("wss://" + this.remoteHost + ":" + this.remotePort); this._socket.onopen = this.onOpen.bind(this); this._socket.onclose = this.onClose.bind(this); this._socket.onmessage = this.onMessage.bind(this); this._socket.onerror = this.onError.bind(this); } onOpen() { if (!this._active) return; this._socket.send(this.transferKey); this.on_start(); } onMessage(data) { if (!this._active) { console.error("Got data, but socket closed?"); return; } this._parseActive = true; let fileReader = new FileReader(); fileReader.onload = (event) => { this.onBinaryData(new Uint8Array(event.target.result)); if (this._socket.readyState !== WebSocket.OPEN && !this._succeed) this.on_fail("unexpected close"); this._parseActive = false; }; fileReader.readAsArrayBuffer(data.data); } onBinaryData(data) { this.currentSize += data.length; this.on_data(data); if (this.currentSize == this.totalSize) { this._succeed = true; this.on_complete(); this.disconnect(); } } onError() { if (!this._active) return; this.on_fail("an error occurent"); this.disconnect(); } onClose() { if (!this._active) return; if (!this._parseActive) this.on_fail("unexpected close"); this.disconnect(); } disconnect() { this._active = false; //this._socket.close(); } } class FileManager { constructor(client) { this.listRequests = []; this.pendingDownloadTransfers = []; this.downloadCounter = 0; this.handle = client; this.icons = new IconManager(this); this.handle.serverConnection.commandHandler["notifyfilelist"] = this.notifyFileList.bind(this); this.handle.serverConnection.commandHandler["notifyfilelistfinished"] = this.notifyFileListFinished.bind(this); this.handle.serverConnection.commandHandler["notifystartdownload"] = this.notifyStartDownload.bind(this); } /******************************** File list ********************************/ //TODO multiple requests (same path) requestFileList(path, channel, password) { const _this = this; return new Promise((accept, reject) => { let req = new FileListRequest(); req.path = path; req.entries = []; req.callback = accept; _this.listRequests.push(req); _this.handle.serverConnection.sendCommand("ftgetfilelist", { "path": path, "cid": (channel ? channel.channelId : "0"), "cpw": (password ? password : "") }).then(() => { }).catch(reason => { _this.listRequests.remove(req); if (reason instanceof CommandResult) { if (reason.id == 0x0501) { accept([]); //Empty result return; } } reject(reason); }); }); } notifyFileList(json) { let entry = undefined; for (let e of this.listRequests) { if (e.path == json[0]["path"]) { entry = e; break; } } if (!entry) { console.error("Invalid file list entry. Path: " + json[0]["path"]); return; } for (let e of json) entry.entries.push(e); } notifyFileListFinished(json) { let entry = undefined; for (let e of this.listRequests) { if (e.path == json[0]["path"]) { entry = e; this.listRequests.remove(e); break; } } if (!entry) { console.error("Invalid file list entry finish. Path: " + json[0]["path"]); return; } entry.callback(entry.entries); } /******************************** File download ********************************/ requestFileDownload(path, file, channel, password) { const _this = this; let transfer = new DownloadFileTransfer(this, this.downloadCounter++); this.pendingDownloadTransfers.push(transfer); return new Promise((resolve, reject) => { transfer["_promiseCallback"] = resolve; _this.handle.serverConnection.sendCommand("ftinitdownload", { "path": path, "name": file, "cid": (channel ? channel.channelId : "0"), "cpw": (password ? password : ""), "clientftfid": transfer.transferId }).catch(reason => { _this.pendingDownloadTransfers.remove(transfer); reject(reason); }); }); } notifyStartDownload(json) { json = json[0]; let transfer; for (let e of this.pendingDownloadTransfers) if (e.transferId == json["clientftfid"]) { transfer = e; break; } transfer.serverTransferId = json["serverftfid"]; transfer.transferKey = json["ftkey"]; transfer.totalSize = json["size"]; transfer.remotePort = json["port"]; transfer.remoteHost = json["ip"].replace(/,/g, ""); if (transfer.remoteHost == '0.0.0.0' || transfer.remoteHost == '127.168.0.0') transfer.remoteHost = this.handle.serverConnection._remoteHost; transfer["_promiseCallback"](transfer); this.pendingDownloadTransfers.remove(transfer); } } class Icon { } class IconManager { constructor(handle) { this.handle = handle; } iconList() { return this.handle.requestFileList("/icons"); } downloadIcon(id) { return this.handle.requestFileDownload("", "/icon_" + id); } resolveCached(id) { let icon = localStorage.getItem("icon_" + id); if (icon) { let i = JSON.parse(icon); if (i.base64.length > 0) { return i; } } return undefined; } loadIcon(id) { const _this = this; return new Promise((resolve, reject) => { let icon = this.resolveCached(id); if (icon) { resolve(icon); return; } _this.downloadIcon(id).then(ft => { let array = new Uint8Array(0); ft.on_fail = reason => { console.error("Could not download icon " + id + " -> " + reason); reject(reason); }; ft.on_start = () => { }; ft.on_data = (data) => { array = concatenate(Uint8Array, array, data); }; ft.on_complete = () => { let base64 = btoa(String.fromCharCode.apply(null, array)); let icon = new Icon(); icon.base64 = base64; icon.id = id; icon.name = "icon_" + id; localStorage.setItem("icon_" + id, JSON.stringify(icon)); resolve(icon); }; ft.startTransfer(); }).catch(reason => { console.error("Error while downloading icon! (" + JSON.stringify(reason) + ")"); reject(reason); }); }); } //$("\"tick\"") generateTag(id) { if (id == 0) return $("
"); else if (id < 1000) return $("
"); let tag = $("
"); tag.addClass("icon_empty"); let img = $.spawn("img"); img.attr("width", 16).attr("height", 16).attr("alt", ""); let icon = this.resolveCached(id); if (icon) { img.attr("src", "data:image/png;base64," + icon.base64); tag.append(img); } else { img.attr("src", "file://null"); let loader = $("
"); loader.addClass("icon_loading"); tag.append(loader); this.loadIcon(id).then(icon => { img.attr("src", "data:image/png;base64," + icon.base64); console.debug("Icon " + id + " loaded :)"); img.css("opacity", 0); tag.append(img); loader.animate({ opacity: 0 }, 50, function () { $(this).detach(); img.animate({ opacity: 1 }, 150); }); }).catch(reason => { console.error("Could not load icon " + id + ". Reason: " + reason); }); } return tag; } } //# sourceMappingURL=FileManager.js.map