mirror of
https://github.com/qbittorrent/qBittorrent
synced 2025-08-19 21:03:30 -07:00
Add new Add Torrent experience to WebUI
This dialog more closely mimics the dialog presented by the GUI. It includes information about the contents of a torrent. Signed-off-by: Thomas Piccirello <thomas@piccirello.com>
This commit is contained in:
parent
3ecb5a583c
commit
5963fc2032
14 changed files with 607 additions and 413 deletions
|
@ -155,7 +155,8 @@ Required by:
|
|||
width: 5px;
|
||||
}
|
||||
|
||||
#desktopNavbar li ul li a {
|
||||
#desktopNavbar li ul li a,
|
||||
#desktopNavbar li ul li div.anchor {
|
||||
color: var(--color-text-default);
|
||||
font-weight: normal;
|
||||
min-width: 155px;
|
||||
|
@ -163,7 +164,8 @@ Required by:
|
|||
position: relative;
|
||||
}
|
||||
|
||||
#desktopNavbar li ul li a:hover {
|
||||
#desktopNavbar li ul li a:hover,
|
||||
#desktopNavbar li ul li div.anchor:hover {
|
||||
background-color: var(--color-background-hover);
|
||||
color: var(--color-text-white);
|
||||
}
|
||||
|
|
|
@ -184,6 +184,16 @@ div.mochaToolbarWrapper.bottom {
|
|||
width: 16px;
|
||||
}
|
||||
|
||||
.mochaErrorIcon {
|
||||
background: url("../images/error.svg") no-repeat;
|
||||
background-size: 16px;
|
||||
bottom: 7px;
|
||||
height: 16px;
|
||||
left: 6px;
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.mochaIframe {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -672,6 +672,17 @@ td.generalLabel {
|
|||
width: 1px;
|
||||
}
|
||||
|
||||
td.fullWidth {
|
||||
box-sizing: border-box;
|
||||
max-width: none;
|
||||
width: 100%;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
td.noWrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#tristate_cb {
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
|
@ -835,7 +846,8 @@ td.statusBarSeparator {
|
|||
color: var(--color-text-green);
|
||||
}
|
||||
|
||||
#torrentFilesTableDiv .dynamicTable tr.nonAlt:hover {
|
||||
#torrentFilesTableDiv .dynamicTable tr.nonAlt:hover,
|
||||
#addTorrentFilesTableDiv .dynamicTable tr.nonAlt:hover {
|
||||
background-color: var(--color-background-hover);
|
||||
color: var(--color-text-white);
|
||||
}
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>QBT_TR(Add Torrent Links)QBT_TR[CONTEXT=downloadFromURL]</title>
|
||||
<title>QBT_TR(Add Torrent Links)QBT_TR[CONTEXT=DownloadFromURLDialog]</title>
|
||||
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
|
||||
<link rel="stylesheet" href="css/Window.css?v=${CACHEID}" type="text/css">
|
||||
<script defer src="scripts/localpreferences.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/color-scheme.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/download.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/pathAutofill.js?v=${CACHEID}"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", (event) => {
|
||||
document.getElementById("urls").focus();
|
||||
|
||||
const encodedUrls = new URLSearchParams(window.location.search).get("urls");
|
||||
if (encodedUrls !== null) {
|
||||
const urls = encodedUrls.split("|").map(decodeURIComponent);
|
||||
|
@ -21,172 +21,42 @@
|
|||
document.getElementById("urls").value = urls.join("\n");
|
||||
}
|
||||
|
||||
let submitted = false;
|
||||
document.getElementById("submitButton").addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
document.getElementById("downloadForm").addEventListener("submit", (event) => {
|
||||
document.getElementById("startTorrentHidden").value = document.getElementById("startTorrent").checked ? "false" : "true";
|
||||
const urls = document.getElementById("urls").value.split("\n").map(s => s.trim()).filter(s => (s.length > 0));
|
||||
if (urls.length === 0)
|
||||
return;
|
||||
|
||||
document.getElementById("dlLimitHidden").value = Number(document.getElementById("dlLimitText").value) * 1024;
|
||||
document.getElementById("upLimitHidden").value = Number(document.getElementById("upLimitText").value) * 1024;
|
||||
for (const url of urls)
|
||||
window.parent.qBittorrent.Client.createAddTorrentWindow("QBT_TR(Magnet link)QBT_TR[CONTEXT=DownloadFromURLDialog]", url);
|
||||
|
||||
document.getElementById("download_spinner").style.display = "block";
|
||||
submitted = true;
|
||||
window.parent.qBittorrent.Client.closeFrameWindow(window);
|
||||
});
|
||||
|
||||
document.getElementById("download_frame").addEventListener("load", (event) => {
|
||||
if (submitted)
|
||||
window.parent.qBittorrent.Client.closeFrameWindow(window);
|
||||
window.addEventListener("keydown", (event) => {
|
||||
switch (event.key) {
|
||||
case "Escape":
|
||||
event.preventDefault();
|
||||
window.parent.qBittorrent.Client.closeFrameWindow(window);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
window.qBittorrent.pathAutofill.attachPathAutofill();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<iframe id="download_frame" name="download_frame" class="invisible" title="" src="about:blank"></iframe>
|
||||
<form action="api/v2/torrents/add" enctype="multipart/form-data" method="post" id="downloadForm" style="text-align: center;" target="download_frame" autocorrect="off" autocapitalize="none">
|
||||
<div style="text-align: center;">
|
||||
<br>
|
||||
<h2><label for="urls">QBT_TR(Add torrent links)QBT_TR[CONTEXT=AddNewTorrentDialog]</label></h2>
|
||||
<textarea id="urls" rows="10" name="urls"></textarea>
|
||||
<p><i>QBT_TR(One link per line (HTTP links, Magnet links and info-hashes are supported))QBT_TR[CONTEXT=AddNewTorrentDialog]</i></p>
|
||||
<fieldset class="settings" style="border: 0; text-align: left; margin-top: 6px;">
|
||||
<legend>QBT_TR(Torrent options)QBT_TR[CONTEXT=AddNewTorrentDialog]</legend>
|
||||
<table style="margin: auto;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
|
||||
<option selected value="false">QBT_TR(Manual)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="true">QBT_TR(Automatic)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="savepath">QBT_TR(Save files to location:)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="savepath" name="savepath" class="pathDirectory" style="width: 16em;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="rename">QBT_TR(Rename torrent)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="rename" name="rename" style="width: 16em;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label id="categoryLabel" for="categorySelect">QBT_TR(Category:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="select-watched-folder-editable">
|
||||
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
|
||||
<option selected value="\other"></option>
|
||||
</select>
|
||||
<input type="text" name="category" aria-labelledby="categoryLabel">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="startTorrent">QBT_TR(Start torrent)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="startTorrentHidden" name="stopped">
|
||||
<input type="checkbox" id="startTorrent">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="addToTopOfQueue">QBT_TR(Add to top of queue)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="addToTopOfQueue" name="addToTopOfQueue" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="stopCondition">QBT_TR(Stop condition:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="stopCondition" name="stopCondition">
|
||||
<option selected value="None">QBT_TR(None)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="MetadataReceived">QBT_TR(Metadata received)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="FilesChecked">QBT_TR(Files checked)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="skip_checking">QBT_TR(Skip hash check)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="skip_checking" name="skip_checking" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="contentLayout">QBT_TR(Content layout:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="contentLayout" name="contentLayout">
|
||||
<option selected value="Original">QBT_TR(Original)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="Subfolder">QBT_TR(Create subfolder)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="NoSubfolder">QBT_TR(Don't create subfolder)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="sequentialDownload">QBT_TR(Download in sequential order)QBT_TR[CONTEXT=TransferListWidget]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="sequentialDownload" name="sequentialDownload" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="firstLastPiecePrio">QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=TransferListWidget]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="firstLastPiecePrio" name="firstLastPiecePrio" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="dlLimitText">QBT_TR(Limit download rate)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="dlLimitHidden" name="dlLimit">
|
||||
<input type="text" id="dlLimitText" style="width: 16em;" placeholder="KiB/s">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="upLimitText">QBT_TR(Limit upload rate)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="upLimitHidden" name="upLimit">
|
||||
<input type="text" id="upLimitText" style="width: 16em;" placeholder="KiB/s">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="submitbutton" style="margin-top: 12px; text-align: center;">
|
||||
<button type="submit" id="submitButton">QBT_TR(Download)QBT_TR[CONTEXT=downloadFromURL]</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div style="text-align: center;">
|
||||
<br>
|
||||
<h2 class="vcenter">QBT_TR(Add torrent links)QBT_TR[CONTEXT=DownloadFromURLDialog]</h2>
|
||||
<textarea id="urls" name="urls" rows="10" required style="width: 80%;" aria-label="QBT_TR(URLs)QBT_TR[CONTEXT=DownloadFromURLDialog]"></textarea>
|
||||
<p><i>QBT_TR(One link per line (HTTP links, Magnet links and info-hashes are supported))QBT_TR[CONTEXT=DownloadFromURLDialog]</i></p>
|
||||
<div id="submitbutton" style="margin-top: 12px; text-align: center;">
|
||||
<button type="submit" id="submitButton">QBT_TR(Download)QBT_TR[CONTEXT=DownloadFromURLDialog]</button>
|
||||
</div>
|
||||
</form>
|
||||
<div id="download_spinner" class="mochaSpinner"></div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -60,7 +60,15 @@
|
|||
<li>
|
||||
<a class="returnFalse">QBT_TR(File)QBT_TR[CONTEXT=MainWindow]</a>
|
||||
<ul>
|
||||
<li><a id="uploadLink"><img class="MyMenuIcon" alt="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/list-add.svg" width="16" height="16">QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]</a></li>
|
||||
<li>
|
||||
<div id="uploadLink" class="anchor">
|
||||
<label id="uploadLinkLabel" for="fileselectLink" style="cursor: pointer;">
|
||||
<img class="MyMenuIcon" alt="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/list-add.svg" width="16" height="16">
|
||||
<span>QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]</span>
|
||||
</label>
|
||||
<input type="file" id="fileselectLink" accept=".torrent, application/x-bittorrent" name="fileselect[]" multiple style="display: none;">
|
||||
</div>
|
||||
</li>
|
||||
<li><a id="downloadLink"><img class="MyMenuIcon" alt="QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]" src="images/insert-link.svg" width="16" height="16">QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]</a></li>
|
||||
<li class="divider"><a id="logoutLink"><img class="MyMenuIcon" alt="QBT_TR(Logout)QBT_TR[CONTEXT=HttpServer]" src="images/system-log-out.svg" width="16" height="16">QBT_TR(Logout)QBT_TR[CONTEXT=HttpServer]</a></li>
|
||||
<li><a id="shutdownLink"><img class="MyMenuIcon" alt="QBT_TR(Exit qBittorrent)QBT_TR[CONTEXT=HttpServer]" src="images/application-exit.svg" width="16" height="16">QBT_TR(Exit qBittorrent)QBT_TR[CONTEXT=HttpServer]</a></li>
|
||||
|
@ -114,8 +122,13 @@
|
|||
</div>
|
||||
<div id="mochaToolbar">
|
||||
|
||||
<a id="uploadButton"><img class="mochaToolButton" title="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/list-add.svg" alt="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24"></a>
|
||||
<a id="downloadButton"><img class="mochaToolButton" title="QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]" src="images/insert-link.svg" alt="QBT_TR(Add Torrent Link...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24"></a>
|
||||
<div id="uploadButton" style="display: inline-block;">
|
||||
<label for="fileselectButton" style="cursor: pointer;">
|
||||
<img class="mochaToolButton" title="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" src="images/list-add.svg" alt="QBT_TR(Add Torrent File...)QBT_TR[CONTEXT=MainWindow]" width="24" height="24">
|
||||
</label>
|
||||
<input type="file" id="fileselectButton" accept=".torrent, application/x-bittorrent" name="fileselect[]" multiple style="display: none;">
|
||||
</div>
|
||||
<a id="deleteButton"><img class="mochaToolButton" title="QBT_TR(Remove)QBT_TR[CONTEXT=TransferListWidget]" src="images/list-remove.svg" alt="QBT_TR(Remove)QBT_TR[CONTEXT=TransferListWidget]" width="24" height="24"></a>
|
||||
<a id="startButton" class="divider"><img class="mochaToolButton" title="QBT_TR(Start)QBT_TR[CONTEXT=TransferListWidget]" src="images/torrent-start.svg" alt="QBT_TR(Start)QBT_TR[CONTEXT=TransferListWidget]" width="24" height="24"></a>
|
||||
<a id="stopButton"><img class="mochaToolButton" title="QBT_TR(Stop)QBT_TR[CONTEXT=TransferListWidget]" src="images/torrent-stop.svg" alt="QBT_TR(Stop)QBT_TR[CONTEXT=TransferListWidget]" width="24" height="24"></a>
|
||||
|
|
|
@ -24,16 +24,22 @@
|
|||
"use strict";
|
||||
|
||||
window.qBittorrent ??= {};
|
||||
window.qBittorrent.Download ??= (() => {
|
||||
window.qBittorrent.AddTorrent ??= (() => {
|
||||
const exports = () => {
|
||||
return {
|
||||
changeCategorySelect: changeCategorySelect,
|
||||
changeTMM: changeTMM
|
||||
changeTMM: changeTMM,
|
||||
loadMetadata: loadMetadata,
|
||||
metadataCompleted: metadataCompleted,
|
||||
populateMetadata: populateMetadata,
|
||||
setWindowId: setWindowId
|
||||
};
|
||||
};
|
||||
|
||||
let categories = {};
|
||||
let defaultSavePath = "";
|
||||
let windowId = "";
|
||||
let source;
|
||||
|
||||
const getCategories = () => {
|
||||
fetch("api/v2/torrents/categories", {
|
||||
|
@ -131,6 +137,80 @@ window.qBittorrent.Download ??= (() => {
|
|||
}
|
||||
};
|
||||
|
||||
let loadMetadataTimer;
|
||||
const loadMetadata = (sourceUrl = undefined) => {
|
||||
if (sourceUrl)
|
||||
source = sourceUrl;
|
||||
|
||||
fetch("api/v2/torrents/fetchMetadata", {
|
||||
method: "POST",
|
||||
body: new URLSearchParams({
|
||||
source: source
|
||||
})
|
||||
})
|
||||
.then(async (response) => {
|
||||
if (!response.ok)
|
||||
metadataFailed();
|
||||
|
||||
const data = await response.json();
|
||||
populateMetadata(data);
|
||||
|
||||
if (response.status === 200)
|
||||
metadataCompleted();
|
||||
else
|
||||
loadMetadataTimer = loadMetadata.delay(1000);
|
||||
});
|
||||
};
|
||||
|
||||
const metadataCompleted = (showDownloadButton = true) => {
|
||||
clearTimeout(loadMetadataTimer);
|
||||
|
||||
document.getElementById("metadataStatus").destroy();
|
||||
document.getElementById("loading_spinner").style.display = "none";
|
||||
|
||||
if (showDownloadButton)
|
||||
document.getElementById("saveTorrent").classList.remove("invisible");
|
||||
};
|
||||
|
||||
const metadataFailed = () => {
|
||||
clearTimeout(loadMetadataTimer);
|
||||
|
||||
document.getElementById("metadataStatus").textContent = "Metadata retrieval failed";
|
||||
document.getElementById("metadataStatus").classList.add("red");
|
||||
document.getElementById("loading_spinner").style.display = "none";
|
||||
document.getElementById("error_icon").classList.remove("invisible");
|
||||
};
|
||||
|
||||
const populateMetadata = (metadata) => {
|
||||
// update window title
|
||||
if (metadata.info?.name)
|
||||
window.parent.document.getElementById(`${windowId}_title`).textContent = metadata.info.name;
|
||||
|
||||
document.getElementById("infoHashV1").textContent = metadata.infohash_v1 || "N/A";
|
||||
document.getElementById("infoHashV2").textContent = metadata.infohash_v2 || "N/A";
|
||||
|
||||
if (metadata.info?.length)
|
||||
document.getElementById("size").textContent = window.qBittorrent.Misc.friendlyUnit(metadata.info.length, false);
|
||||
if (metadata.creation_date && (metadata.creation_date > 1))
|
||||
document.getElementById("createdDate").textContent = new Date(metadata.creation_date * 1000).toLocaleString();
|
||||
if (metadata.comment)
|
||||
document.getElementById("comment").textContent = metadata.comment;
|
||||
|
||||
if (metadata.info?.files) {
|
||||
const files = metadata.info.files.map((file, index) => ({
|
||||
index: index,
|
||||
name: file.path,
|
||||
size: file.length,
|
||||
priority: window.qBittorrent.FileTree.FilePriority.Normal,
|
||||
}));
|
||||
window.qBittorrent.TorrentContent.updateData(files);
|
||||
}
|
||||
};
|
||||
|
||||
const setWindowId = (id) => {
|
||||
windowId = id;
|
||||
};
|
||||
|
||||
window.addEventListener("load", async (event) => {
|
||||
// user might load this page directly (via browser magnet handler)
|
||||
// so wait for crucial initialization to complete
|
||||
|
@ -142,4 +222,4 @@ window.qBittorrent.Download ??= (() => {
|
|||
|
||||
return exports();
|
||||
})();
|
||||
Object.freeze(window.qBittorrent.Download);
|
||||
Object.freeze(window.qBittorrent.AddTorrent);
|
|
@ -42,7 +42,9 @@ window.qBittorrent.Client ??= (() => {
|
|||
showLogViewer: showLogViewer,
|
||||
isShowSearchEngine: isShowSearchEngine,
|
||||
isShowRssReader: isShowRssReader,
|
||||
isShowLogViewer: isShowLogViewer
|
||||
isShowLogViewer: isShowLogViewer,
|
||||
createAddTorrentWindow: createAddTorrentWindow,
|
||||
uploadTorrentFiles: uploadTorrentFiles
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -121,6 +123,90 @@ window.qBittorrent.Client ??= (() => {
|
|||
return showingLogViewer;
|
||||
};
|
||||
|
||||
const createAddTorrentWindow = (title, source, metadata = undefined) => {
|
||||
const isFirefox = navigator.userAgent.includes("Firefox");
|
||||
const isSafari = navigator.userAgent.includes("AppleWebKit") && !navigator.userAgent.includes("Chrome");
|
||||
let height = 855;
|
||||
if (isSafari)
|
||||
height -= 40;
|
||||
else if (isFirefox)
|
||||
height -= 10;
|
||||
|
||||
const staticId = "uploadPage";
|
||||
const id = `${staticId}-${encodeURIComponent(source)}`;
|
||||
|
||||
const contentURL = new URL("addtorrent.html", window.location);
|
||||
contentURL.search = new URLSearchParams({
|
||||
source: source,
|
||||
fetch: metadata === undefined,
|
||||
windowId: id
|
||||
});
|
||||
|
||||
new MochaUI.Window({
|
||||
id: id,
|
||||
icon: "images/qbittorrent-tray.svg",
|
||||
title: title,
|
||||
loadMethod: "iframe",
|
||||
contentURL: contentURL.toString(),
|
||||
scrollbars: true,
|
||||
maximizable: false,
|
||||
paddingVertical: 0,
|
||||
paddingHorizontal: 0,
|
||||
width: loadWindowWidth(staticId, 980),
|
||||
height: loadWindowHeight(staticId, height),
|
||||
onResize: window.qBittorrent.Misc.createDebounceHandler(500, (e) => {
|
||||
saveWindowSize(staticId, id);
|
||||
}),
|
||||
onContentLoaded: () => {
|
||||
if (metadata !== undefined)
|
||||
document.getElementById(`${id}_iframe`).contentWindow.postMessage(metadata, window.origin);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const uploadTorrentFiles = (files) => {
|
||||
const fileNames = [];
|
||||
const formData = new FormData();
|
||||
for (const file of files) {
|
||||
fileNames.push(file.name);
|
||||
formData.append("file", file);
|
||||
}
|
||||
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", "api/v2/torrents/parseMetadata");
|
||||
xhr.addEventListener("readystatechange", () => {
|
||||
if (xhr.readyState === 4) { // DONE state
|
||||
if ((xhr.status >= 200) && (xhr.status < 300)) {
|
||||
let response;
|
||||
try {
|
||||
response = JSON.parse(xhr.responseText);
|
||||
}
|
||||
catch (error) {
|
||||
alert("QBT_TR(Unable to parse response)QBT_TR[CONTEXT=HttpServer]");
|
||||
return;
|
||||
}
|
||||
|
||||
for (const fileName of fileNames) {
|
||||
let title = fileName;
|
||||
const metadata = response[fileName];
|
||||
if (metadata !== undefined)
|
||||
title = metadata.name;
|
||||
|
||||
createAddTorrentWindow(title, metadata.hash, metadata);
|
||||
}
|
||||
}
|
||||
else if (xhr.responseText) {
|
||||
alert(xhr.responseText);
|
||||
}
|
||||
}
|
||||
});
|
||||
xhr.addEventListener("error", () => {
|
||||
if (xhr.responseText)
|
||||
alert(xhr.responseText);
|
||||
});
|
||||
xhr.send(formData);
|
||||
};
|
||||
|
||||
return exports();
|
||||
})();
|
||||
Object.freeze(window.qBittorrent.Client);
|
||||
|
@ -1677,32 +1763,11 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
// can't handle folder due to cannot put the filelist (from dropped folder)
|
||||
// to <input> `files` field
|
||||
for (const item of ev.dataTransfer.items) {
|
||||
if (item.webkitGetAsEntry().isDirectory)
|
||||
if ((item.kind !== "file") || (item.webkitGetAsEntry().isDirectory))
|
||||
return;
|
||||
}
|
||||
|
||||
const id = "uploadPage";
|
||||
new MochaUI.Window({
|
||||
id: id,
|
||||
icon: "images/qbittorrent-tray.svg",
|
||||
title: "QBT_TR(Upload local torrent)QBT_TR[CONTEXT=HttpServer]",
|
||||
loadMethod: "iframe",
|
||||
contentURL: "upload.html",
|
||||
addClass: "windowFrame", // fixes iframe scrolling on iOS Safari
|
||||
scrollbars: true,
|
||||
maximizable: false,
|
||||
paddingVertical: 0,
|
||||
paddingHorizontal: 0,
|
||||
width: loadWindowWidth(id, 500),
|
||||
height: loadWindowHeight(id, 460),
|
||||
onResize: window.qBittorrent.Misc.createDebounceHandler(500, (e) => {
|
||||
saveWindowSize(id);
|
||||
}),
|
||||
onContentLoaded: () => {
|
||||
const fileInput = document.getElementById(`${id}_iframe`).contentDocument.getElementById("fileselect");
|
||||
fileInput.files = droppedFiles;
|
||||
}
|
||||
});
|
||||
window.qBittorrent.Client.uploadTorrentFiles(droppedFiles);
|
||||
}
|
||||
|
||||
const droppedText = ev.dataTransfer.getData("text");
|
||||
|
@ -1720,32 +1785,8 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
|| ((str.length === 32) && !(/[^2-7A-Z]/i.test(str))); // v1 Base32 encoded SHA-1 info-hash
|
||||
});
|
||||
|
||||
if (urls.length <= 0)
|
||||
return;
|
||||
|
||||
const id = "downloadPage";
|
||||
const contentURL = new URL("download.html", window.location);
|
||||
contentURL.search = new URLSearchParams({
|
||||
urls: urls.map(encodeURIComponent).join("|")
|
||||
});
|
||||
new MochaUI.Window({
|
||||
id: id,
|
||||
icon: "images/qbittorrent-tray.svg",
|
||||
title: "QBT_TR(Download from URLs)QBT_TR[CONTEXT=downloadFromURL]",
|
||||
loadMethod: "iframe",
|
||||
contentURL: contentURL.toString(),
|
||||
addClass: "windowFrame", // fixes iframe scrolling on iOS Safari
|
||||
scrollbars: true,
|
||||
maximizable: false,
|
||||
closable: true,
|
||||
paddingVertical: 0,
|
||||
paddingHorizontal: 0,
|
||||
width: loadWindowWidth(id, 500),
|
||||
height: loadWindowHeight(id, 600),
|
||||
onResize: window.qBittorrent.Misc.createDebounceHandler(500, (e) => {
|
||||
saveWindowSize(id);
|
||||
})
|
||||
});
|
||||
for (const url of urls)
|
||||
qBittorrent.Client.createAddTorrentWindow(url, url);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -44,6 +44,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
TorrentTrackersTable: TorrentTrackersTable,
|
||||
BulkRenameTorrentFilesTable: BulkRenameTorrentFilesTable,
|
||||
TorrentFilesTable: TorrentFilesTable,
|
||||
AddTorrentFilesTable: AddTorrentFilesTable,
|
||||
LogMessageTable: LogMessageTable,
|
||||
LogPeerTable: LogPeerTable,
|
||||
RssFeedTable: RssFeedTable,
|
||||
|
@ -66,6 +67,9 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
|
||||
let DynamicTableHeaderContextMenuClass = null;
|
||||
|
||||
if (typeof LocalPreferences === "undefined")
|
||||
window.LocalPreferences = new window.qBittorrent.LocalPreferences.LocalPreferences();
|
||||
|
||||
class DynamicTable {
|
||||
setup(dynamicTableDivId, dynamicTableFixedHeaderDivId, contextMenu, useVirtualList = false) {
|
||||
this.dynamicTableDivId = dynamicTableDivId;
|
||||
|
@ -2894,16 +2898,18 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.columns["size"].updateTd = displaySize;
|
||||
|
||||
// progress
|
||||
this.columns["progress"].updateTd = function(td, row) {
|
||||
const value = Number(this.getRowValue(row));
|
||||
if (this.columns["progress"]) {
|
||||
this.columns["progress"].updateTd = function(td, row) {
|
||||
const value = Number(this.getRowValue(row));
|
||||
|
||||
const progressBar = td.firstElementChild;
|
||||
if (progressBar === null)
|
||||
td.append(new window.qBittorrent.ProgressBar.ProgressBar(value));
|
||||
else
|
||||
progressBar.setValue(value);
|
||||
};
|
||||
this.columns["progress"].staticWidth = 100;
|
||||
const progressBar = td.firstElementChild;
|
||||
if (progressBar === null)
|
||||
td.append(new window.qBittorrent.ProgressBar.ProgressBar(value));
|
||||
else
|
||||
progressBar.setValue(value);
|
||||
};
|
||||
this.columns["progress"].staticWidth = 100;
|
||||
}
|
||||
|
||||
// priority
|
||||
this.columns["priority"].updateTd = function(td, row) {
|
||||
|
@ -2919,8 +2925,10 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
this.columns["priority"].staticWidth = 140;
|
||||
|
||||
// remaining, availability
|
||||
this.columns["remaining"].updateTd = displaySize;
|
||||
this.columns["availability"].updateTd = displayPercentage;
|
||||
if (this.columns["remaining"])
|
||||
this.columns["remaining"].updateTd = displaySize;
|
||||
if (this.columns["availability"])
|
||||
this.columns["availability"].updateTd = displayPercentage;
|
||||
}
|
||||
|
||||
#sortNodesByColumn(root, column) {
|
||||
|
@ -3075,6 +3083,17 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
}
|
||||
}
|
||||
|
||||
class AddTorrentFilesTable extends TorrentFilesTable {
|
||||
initColumns() {
|
||||
this.newColumn("checked", "", "", 50, true);
|
||||
this.newColumn("name", "", "QBT_TR(Name)QBT_TR[CONTEXT=TrackerListWidget]", 190, true);
|
||||
this.newColumn("size", "", "QBT_TR(Total Size)QBT_TR[CONTEXT=TrackerListWidget]", 75, true);
|
||||
this.newColumn("priority", "", "QBT_TR(Download Priority)QBT_TR[CONTEXT=TrackerListWidget]", 140, true);
|
||||
|
||||
this.initColumnsFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
class RssFeedTable extends DynamicTable {
|
||||
initColumns() {
|
||||
this.newColumn("state_icon", "", "", 30, true);
|
||||
|
@ -3253,7 +3272,8 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||
if (!tr)
|
||||
return;
|
||||
|
||||
showDownloadPage([this.getRow(tr.rowId).full_data.torrentURL]);
|
||||
const { name, torrentURL } = this._this.rows.get(this.rowId).full_data;
|
||||
qBittorrent.Client.createAddTorrentWindow(name, torrentURL);
|
||||
});
|
||||
}
|
||||
updateRow(tr, fullUpdate) {
|
||||
|
|
|
@ -150,10 +150,11 @@ let setQueuePositionFN = () => {};
|
|||
let exportTorrentFN = () => {};
|
||||
|
||||
const initializeWindows = () => {
|
||||
saveWindowSize = (windowId) => {
|
||||
const size = document.getElementById(windowId).getSize();
|
||||
LocalPreferences.set(`window_${windowId}_width`, size.x);
|
||||
LocalPreferences.set(`window_${windowId}_height`, size.y);
|
||||
saveWindowSize = (windowName, windowId = windowName) => {
|
||||
const windowInstance = MochaUI.Windows.instances[windowId];
|
||||
const size = windowInstance.contentWrapperEl.getSize();
|
||||
LocalPreferences.set(`window_${windowName}_width`, size.x);
|
||||
LocalPreferences.set(`window_${windowName}_height`, size.y);
|
||||
};
|
||||
|
||||
loadWindowWidth = (windowId, defaultValue) => {
|
||||
|
@ -193,14 +194,13 @@ const initializeWindows = () => {
|
|||
title: "QBT_TR(Download from URLs)QBT_TR[CONTEXT=downloadFromURL]",
|
||||
loadMethod: "iframe",
|
||||
contentURL: contentURL.toString(),
|
||||
addClass: "windowFrame", // fixes iframe scrolling on iOS Safari
|
||||
scrollbars: true,
|
||||
maximizable: false,
|
||||
closable: true,
|
||||
paddingVertical: 0,
|
||||
paddingHorizontal: 0,
|
||||
width: loadWindowWidth(id, 500),
|
||||
height: loadWindowHeight(id, 600),
|
||||
height: loadWindowHeight(id, 300),
|
||||
onResize: window.qBittorrent.Misc.createDebounceHandler(500, (e) => {
|
||||
saveWindowSize(id);
|
||||
})
|
||||
|
@ -283,31 +283,30 @@ const initializeWindows = () => {
|
|||
});
|
||||
});
|
||||
|
||||
addClickEvent("upload", (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const id = "uploadPage";
|
||||
new MochaUI.Window({
|
||||
id: id,
|
||||
icon: "images/qbittorrent-tray.svg",
|
||||
title: "QBT_TR(Upload local torrent)QBT_TR[CONTEXT=HttpServer]",
|
||||
loadMethod: "iframe",
|
||||
contentURL: "upload.html",
|
||||
addClass: "windowFrame", // fixes iframe scrolling on iOS Safari
|
||||
scrollbars: true,
|
||||
maximizable: false,
|
||||
paddingVertical: 0,
|
||||
paddingHorizontal: 0,
|
||||
width: loadWindowWidth(id, 500),
|
||||
height: loadWindowHeight(id, 460),
|
||||
onResize: window.qBittorrent.Misc.createDebounceHandler(500, (e) => {
|
||||
saveWindowSize(id);
|
||||
})
|
||||
});
|
||||
updateMainData();
|
||||
document.querySelector("#uploadButton #fileselectButton").addEventListener("click", function() {
|
||||
// clear the value so that reselecting the same file(s) still triggers the 'change' event
|
||||
this.value = null;
|
||||
});
|
||||
|
||||
// make the entire anchor tag trigger the input, despite the input's label not spanning the entire anchor
|
||||
document.getElementById("uploadLink").addEventListener("click", (e) => {
|
||||
// clear the value so that reselecting the same file(s) still triggers the 'change' event
|
||||
if (e.target === document.getElementById("fileselectLink")) {
|
||||
e.target.value = null;
|
||||
}
|
||||
else {
|
||||
e.preventDefault();
|
||||
document.getElementById("fileselectLink").click();
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll("#uploadButton #fileselectButton, #uploadLink #fileselectLink").forEach((element) => element.addEventListener("change", () => {
|
||||
if (element.files.length === 0)
|
||||
return;
|
||||
|
||||
window.qBittorrent.Client.uploadTorrentFiles(element.files);
|
||||
}));
|
||||
|
||||
globalUploadLimitFN = () => {
|
||||
const contentURL = new URL("speedlimit.html", window.location);
|
||||
contentURL.search = new URLSearchParams({
|
||||
|
@ -1356,4 +1355,8 @@ const initializeWindows = () => {
|
|||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
const userAgent = (navigator.userAgentData?.platform ?? navigator.platform).toLowerCase();
|
||||
if (userAgent.includes("ipad") || userAgent.includes("iphone") || (userAgent.includes("mac") && (navigator.maxTouchPoints > 1)))
|
||||
document.getElementById("fileselect").accept = ".torrent";
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@ window.qBittorrent.PropFiles ??= (() => {
|
|||
|
||||
const onFilePriorityChanged = (fileIds, priority) => {
|
||||
// ignore folders
|
||||
fileIds = fileIds.map(id => parseInt(id, 10)).filter(id => !window.qBittorrent.TorrentContent.isFolder(id));
|
||||
fileIds = fileIds.map(id => Number(id)).filter(id => !window.qBittorrent.TorrentContent.isFolder(id));
|
||||
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
loadTorrentFilesDataTimer = -1;
|
||||
|
|
|
@ -559,15 +559,10 @@ window.qBittorrent.Search ??= (() => {
|
|||
};
|
||||
|
||||
const downloadSearchTorrent = () => {
|
||||
const urls = [];
|
||||
for (const rowID of searchResultsTable.selectedRowsIds())
|
||||
urls.push(searchResultsTable.getRow(rowID).full_data.fileUrl);
|
||||
|
||||
// only proceed if at least 1 row was selected
|
||||
if (!urls.length)
|
||||
return;
|
||||
|
||||
showDownloadPage(urls);
|
||||
for (const rowID of searchResultsTable.selectedRowsIds()) {
|
||||
const { fileName, fileUrl } = searchResultsTable.getRow(rowID).full_data;
|
||||
qBittorrent.Client.createAddTorrentWindow(fileName, fileUrl);
|
||||
}
|
||||
};
|
||||
|
||||
const manageSearchPlugins = () => {
|
||||
|
|
|
@ -3,27 +3,55 @@
|
|||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>QBT_TR(Upload local torrent)QBT_TR[CONTEXT=HttpServer]</title>
|
||||
<title>QBT_TR(Add torrent)QBT_TR[CONTEXT=HttpServer]</title>
|
||||
<link rel="stylesheet" type="text/css" href="css/dynamicTable.css?v=${CACHEID}">
|
||||
<link rel="stylesheet" href="css/style.css?v=${CACHEID}" type="text/css">
|
||||
<link rel="stylesheet" href="css/Window.css?v=${CACHEID}" type="text/css">
|
||||
<script defer src="scripts/lib/MooTools-Core-1.6.0-compat-compressed.js"></script>
|
||||
<script defer src="scripts/lib/MooTools-More-1.6.0-compat-compressed.js"></script>
|
||||
<script defer src="scripts/localpreferences.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/color-scheme.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/download.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/addtorrent.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script defer src="scripts/misc.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script defer src="scripts/pathAutofill.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/file-tree.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/filesystem.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/contextmenu.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script defer src="scripts/dynamicTable.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script defer src="scripts/torrent-content.js?v=${CACHEID}"></script>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
window.addEventListener("DOMContentLoaded", (event) => {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
const source = searchParams.get("source");
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
document.getElementById("urls").value = source;
|
||||
|
||||
// fetch unless explicitly told not to
|
||||
const fetchMetadata = searchParams.get("fetch") !== "false";
|
||||
let submitted = false;
|
||||
|
||||
const windowId = searchParams.get("windowId");
|
||||
window.qBittorrent.AddTorrent.setWindowId(windowId);
|
||||
|
||||
document.getElementById("uploadForm").addEventListener("submit", (event) => {
|
||||
document.getElementById("startTorrentHidden").value = document.getElementById("startTorrent").checked ? "false" : "true";
|
||||
|
||||
document.getElementById("dlLimitHidden").value = Number(document.getElementById("dlLimitText").value) * 1024;
|
||||
document.getElementById("upLimitHidden").value = Number(document.getElementById("upLimitText").value) * 1024;
|
||||
|
||||
document.getElementById("upload_spinner").style.display = "block";
|
||||
document.getElementById("loading_spinner").style.display = "block";
|
||||
submitted = true;
|
||||
|
||||
// ignore folders
|
||||
const priorities = Array.prototype.filter.call(
|
||||
document.getElementsByClassName("combo_priority"), (e) => !window.qBittorrent.TorrentContent.isFolder(Number(e.dataset.fileId))
|
||||
).map((e) => Number(e.value)).filter(p => (p !== -1));
|
||||
document.getElementById("filePriorities").value = priorities;
|
||||
});
|
||||
|
||||
document.getElementById("upload_frame").addEventListener("load", (event) => {
|
||||
|
@ -31,156 +59,276 @@
|
|||
window.parent.qBittorrent.Client.closeFrameWindow(window);
|
||||
});
|
||||
|
||||
const userAgent = (navigator.userAgentData?.platform ?? navigator.platform).toLowerCase();
|
||||
if (userAgent.includes("ipad") || userAgent.includes("iphone") || (userAgent.includes("mac") && (navigator.maxTouchPoints > 1)))
|
||||
document.getElementById("fileselect").accept = ".torrent";
|
||||
document.getElementById("saveTorrent").addEventListener("click", () => {
|
||||
const url = new URL("api/v2/torrents/saveMetadata", window.location);
|
||||
url.search = new URLSearchParams({
|
||||
source: source
|
||||
});
|
||||
|
||||
window.qBittorrent.Misc.downloadFile(url, "torrent.torrent", "QBT_TR(Unable to download torrent file)QBT_TR[CONTEXT=AddNewTorrentDialog]");
|
||||
});
|
||||
|
||||
window.addEventListener("message", (event) => {
|
||||
// ensure event is from a trusted source
|
||||
if (event.origin !== window.origin)
|
||||
return;
|
||||
|
||||
window.qBittorrent.AddTorrent.populateMetadata(event.data);
|
||||
window.qBittorrent.AddTorrent.metadataCompleted(false);
|
||||
});
|
||||
|
||||
window.qBittorrent.pathAutofill.attachPathAutofill();
|
||||
window.qBittorrent.TorrentContent.init("addTorrentFilesTableDiv", window.qBittorrent.DynamicTable.AddTorrentFilesTable);
|
||||
|
||||
if (fetchMetadata)
|
||||
window.qBittorrent.AddTorrent.loadMetadata(source);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ul id="torrentFilesMenu" class="contextMenu">
|
||||
<li class="separator">
|
||||
<a href="#FilePrio" class="arrow-right"><span style="display: inline-block; width: 16px;"></span> QBT_TR(Priority)QBT_TR[CONTEXT=AddNewTorrentDialog]</a>
|
||||
<ul>
|
||||
<li><a href="#FilePrioIgnore"><span style="display: inline-block; width: 16px;"></span> QBT_TR(Do not download)QBT_TR[CONTEXT=AddNewTorrentDialog]</a></li>
|
||||
<li><a href="#FilePrioNormal"><span style="display: inline-block; width: 16px;"></span> QBT_TR(Normal)QBT_TR[CONTEXT=AddNewTorrentDialog]</a></li>
|
||||
<li><a href="#FilePrioHigh"><span style="display: inline-block; width: 16px;"></span> QBT_TR(High)QBT_TR[CONTEXT=AddNewTorrentDialog]</a></li>
|
||||
<li><a href="#FilePrioMaximum"><span style="display: inline-block; width: 16px;"></span> QBT_TR(Maximum)QBT_TR[CONTEXT=AddNewTorrentDialog]</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<iframe id="upload_frame" name="upload_frame" class="invisible" title="" src="about:blank"></iframe>
|
||||
<form action="api/v2/torrents/add" enctype="multipart/form-data" method="post" id="uploadForm" style="text-align: center;" target="upload_frame" autocorrect="off" autocapitalize="none">
|
||||
<div style="margin-top: 25px; display: inline-block; border: 1px solid lightgrey; border-radius: 4px;">
|
||||
<input type="file" id="fileselect" accept=".torrent, application/x-bittorrent" name="fileselect[]" multiple aria-label="QBT_TR(Select .torrent files)QBT_TR[CONTEXT=AddNewTorrentDialog]">
|
||||
</div>
|
||||
<fieldset class="settings" style="border: 0; text-align: left; margin-top: 12px;">
|
||||
<legend>QBT_TR(Torrent options)QBT_TR[CONTEXT=AddNewTorrentDialog]</legend>
|
||||
<table style="margin: auto;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
|
||||
<option selected value="false">QBT_TR(Manual)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="true">QBT_TR(Automatic)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="savepath">QBT_TR(Save files to location:)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="savepath" name="savepath" class="pathDirectory" style="width: 16em;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="rename">QBT_TR(Rename torrent)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="rename" name="rename" style="width: 16em;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label id="categoryLabel" for="categorySelect">QBT_TR(Category:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="select-watched-folder-editable">
|
||||
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
|
||||
<option selected value="\other"></option>
|
||||
</select>
|
||||
<input type="text" name="category" aria-labelledby="categoryLabel">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="startTorrent">QBT_TR(Start torrent)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="startTorrentHidden" name="stopped">
|
||||
<input type="checkbox" id="startTorrent">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="addToTopOfQueue">QBT_TR(Add to top of queue)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="addToTopOfQueue" name="addToTopOfQueue" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="stopCondition">QBT_TR(Stop condition:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="stopCondition" name="stopCondition">
|
||||
<option selected value="None">QBT_TR(None)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="MetadataReceived">QBT_TR(Metadata received)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="FilesChecked">QBT_TR(Files checked)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="skip_checking">QBT_TR(Skip hash check)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="skip_checking" name="skip_checking" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="contentLayout">QBT_TR(Content layout:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="contentLayout" name="contentLayout">
|
||||
<option selected value="Original">QBT_TR(Original)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="Subfolder">QBT_TR(Create subfolder)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="NoSubfolder">QBT_TR(Don't create subfolder)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="sequentialDownload">QBT_TR(Download in sequential order)QBT_TR[CONTEXT=TransferListWidget]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="sequentialDownload" name="sequentialDownload" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="firstLastPiecePrio">QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=TransferListWidget]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="firstLastPiecePrio" name="firstLastPiecePrio" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="dlLimitText">QBT_TR(Limit download rate)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="dlLimitHidden" name="dlLimit">
|
||||
<input type="text" id="dlLimitText" style="width: 16em;" placeholder="KiB/s">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="upLimitText">QBT_TR(Limit upload rate)QBT_TR[CONTEXT=HttpServer]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="upLimitHidden" name="upLimit">
|
||||
<input type="text" id="upLimitText" style="width: 16em;" placeholder="KiB/s">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div id="submitbutton" style="margin-top: 30px; text-align: center;">
|
||||
<button type="submit" style="font-size: 1em;">QBT_TR(Upload Torrents)QBT_TR[CONTEXT=HttpServer]</button>
|
||||
<form action="api/v2/torrents/add" enctype="multipart/form-data" method="post" id="uploadForm" style="text-align: center; padding: 10px 12px;" target="upload_frame" autocorrect="off" autocapitalize="none">
|
||||
<input type="hidden" id="urls" name="urls">
|
||||
<input type="hidden" id="filePriorities" name="filePriorities">
|
||||
<div style="display: flex; width: 100%;">
|
||||
<div style="width: 50%; flex: 1; box-sizing: border-box;">
|
||||
<fieldset class="settings" style="text-align: left;">
|
||||
<legend>QBT_TR(Save at)QBT_TR[CONTEXT=AddNewTorrentDialog]</legend>
|
||||
<table style="width: 100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="autoTMM">QBT_TR(Torrent Management Mode:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="autoTMM" name="autoTMM" onchange="qBittorrent.Download.changeTMM(this)">
|
||||
<option selected value="false">QBT_TR(Manual)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="true">QBT_TR(Automatic)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="savepath">QBT_TR(Save files to location:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="savepath" name="savepath" class="pathDirectory" style="width: 16em;">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
<fieldset class="settings" style="text-align: left;">
|
||||
<legend>QBT_TR(Torrent settings)QBT_TR[CONTEXT=AddNewTorrentDialog]</legend>
|
||||
<table style="width: 100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="rename">QBT_TR(Rename torrent)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" id="rename" name="rename" style="width: 16em;">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label id="categoryLabel" for="categorySelect">QBT_TR(Category:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<div class="select-watched-folder-editable">
|
||||
<select id="categorySelect" onchange="qBittorrent.Download.changeCategorySelect(this)">
|
||||
<option selected value="\other"></option>
|
||||
</select>
|
||||
<input type="text" name="category" aria-labelledby="categoryLabel">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="startTorrent">QBT_TR(Start torrent)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="startTorrentHidden" name="stopped">
|
||||
<input type="checkbox" id="startTorrent">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="stopCondition">QBT_TR(Stop condition:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="stopCondition" name="stopCondition">
|
||||
<option selected value="None">QBT_TR(None)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="MetadataReceived">QBT_TR(Metadata received)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="FilesChecked">QBT_TR(Files checked)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="addToTopOfQueue">QBT_TR(Add to top of queue)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="addToTopOfQueue" name="addToTopOfQueue" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="skip_checking">QBT_TR(Skip hash check)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="skip_checking" name="skip_checking" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="sequentialDownload">QBT_TR(Download in sequential order)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="sequentialDownload" name="sequentialDownload" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="firstLastPiecePrio">QBT_TR(Download first and last pieces first)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" id="firstLastPiecePrio" name="firstLastPiecePrio" value="true">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="contentLayout">QBT_TR(Content layout:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<select id="contentLayout" name="contentLayout">
|
||||
<option selected value="Original">QBT_TR(Original)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="Subfolder">QBT_TR(Create subfolder)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
<option value="NoSubfolder">QBT_TR(Don't create subfolder)QBT_TR[CONTEXT=AddNewTorrentDialog]</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="dlLimitText">QBT_TR(Limit download rate)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="dlLimitHidden" name="dlLimit">
|
||||
<input type="text" id="dlLimitText" style="width: 16em;" placeholder="KiB/s">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label for="upLimitText">QBT_TR(Limit upload rate)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="hidden" id="upLimitHidden" name="upLimit">
|
||||
<input type="text" id="upLimitText" style="width: 16em;" placeholder="KiB/s">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="settings" style="text-align: left;">
|
||||
<legend>QBT_TR(Torrent information)QBT_TR[CONTEXT=AddNewTorrentDialog]</legend>
|
||||
<table style="width: 100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="noWrap">
|
||||
<label for="size">QBT_TR(Size:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td class="fullWidth">
|
||||
<span id="size">QBT_TR(Not available)QBT_TR[CONTEXT=AddNewTorrentDialog]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="noWrap">
|
||||
<label for="createdDate">QBT_TR(Date:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td class="fullWidth">
|
||||
<span id="createdDate">QBT_TR(Not available)QBT_TR[CONTEXT=AddNewTorrentDialog]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="noWrap">
|
||||
<label for="infoHashV1">QBT_TR(Info hash v1:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td class="fullWidth">
|
||||
<span id="infoHashV1">QBT_TR(Not available)QBT_TR[CONTEXT=AddNewTorrentDialog]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="noWrap">
|
||||
<label for="infoHashV2">QBT_TR(Info hash v2:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td class="fullWidth">
|
||||
<span id="infoHashV2">QBT_TR(Not available)QBT_TR[CONTEXT=AddNewTorrentDialog]</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="noWrap">
|
||||
<label for="comment">QBT_TR(Comment:)QBT_TR[CONTEXT=AddNewTorrentDialog]</label>
|
||||
</td>
|
||||
<td class="fullWidth">
|
||||
<textarea id="comment" rows="6" readonly style="width: calc(100% - 10px); resize: none;"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div style="width: 50%; flex: 1; height: 750px; overflow-y: auto; box-sizing: border-box;">
|
||||
<fieldset class="settings" style="text-align: left; display: flex; flex-direction: column; height: 100%; box-sizing: border-box;">
|
||||
<legend style="width: fit-content;">QBT_TR(Files)QBT_TR[CONTEXT=AddNewTorrentDialog]</legend>
|
||||
<div style="text-align: right; padding-bottom: 10px;">
|
||||
<input type="text" id="torrentFilesFilterInput" placeholder="QBT_TR(Filter files...)QBT_TR[CONTEXT=AddNewTorrentDialog]" aria-label="QBT_TR(Filter files...)QBT_TR[CONTEXT=AddNewTorrentDialog]" autocorrect="off" autocapitalize="none">
|
||||
</div>
|
||||
<div id="torrentFiles" style="overflow: auto;">
|
||||
<div id="torrentFilesTableFixedHeaderDiv" class="dynamicTableFixedHeaderDiv">
|
||||
<table class="dynamicTable" style="position:relative;">
|
||||
<thead>
|
||||
<tr class="dynamicTableHeader"></tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
<div id="addTorrentFilesTableDiv" class="dynamicTableDiv">
|
||||
<table class="dynamicTable">
|
||||
<thead>
|
||||
<tr class="dynamicTableHeader"></tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div id="submitbutton" style="display: flex; margin-top: 10px; align-items: center; position: relative;">
|
||||
<div id="loading_spinner" class="mochaSpinner" style="display: block; bottom: 2px;"></div>
|
||||
<div id="error_icon" class="mochaErrorIcon invisible" style="bottom: 2px;"></div>
|
||||
<span id="metadataStatus" style="padding-left: 28px;">Retrieving metadata</span>
|
||||
<button id="saveTorrent" type="button" class="invisible" style="font-size: 1em;">QBT_TR(Save as .torrent file)QBT_TR[CONTEXT=AddNewTorrentDialog]</button>
|
||||
<!-- maintains button's relative position after metadataStatus element is deleted -->
|
||||
<span> </span>
|
||||
<div style="position: absolute; left: 50%; transform: translateX(-50%);">
|
||||
<button type="submit" style="font-size: 1em;">QBT_TR(Add Torrent)QBT_TR[CONTEXT=AddNewTorrentDialog]</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div id="upload_spinner" class="mochaSpinner"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -294,10 +294,10 @@
|
|||
menu: "rssArticleMenu",
|
||||
actions: {
|
||||
Download: (el) => {
|
||||
let dlString = "";
|
||||
for (const rowID of rssArticleTable.selectedRows)
|
||||
dlString += `${rssArticleTable.getRow(rowID).full_data.torrentURL}\n`;
|
||||
showDownloadPage([dlString]);
|
||||
for (const rowID of rssArticleTable.selectedRows) {
|
||||
const { name, torrentURL } = rssArticleTable.getRow(rowID).full_data;
|
||||
window.qBittorrent.Client.createAddTorrentWindow(name, torrentURL);
|
||||
}
|
||||
},
|
||||
OpenNews: (el) => {
|
||||
for (const rowID of rssArticleTable.selectedRows)
|
||||
|
|
|
@ -392,11 +392,11 @@
|
|||
<file>private/rename_file.html</file>
|
||||
<file>private/rename_files.html</file>
|
||||
<file>private/rename_rule.html</file>
|
||||
<file>private/scripts/addtorrent.js</file>
|
||||
<file>private/scripts/cache.js</file>
|
||||
<file>private/scripts/client.js</file>
|
||||
<file>private/scripts/color-scheme.js</file>
|
||||
<file>private/scripts/contextmenu.js</file>
|
||||
<file>private/scripts/download.js</file>
|
||||
<file>private/scripts/dynamicTable.js</file>
|
||||
<file>private/scripts/file-tree.js</file>
|
||||
<file>private/scripts/filesystem.js</file>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue