mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-06-27 17:09:53 -04:00
WebUI: switch to lightweight clipboard library
The new library [1] will opt to the modern Clipboard API [2] when it is available. It will fallback to the old method otherwise. The new library is also smaller and without any bloat. Note that the line `module.exports` is required to be removed/commented out. This is the only patch required. [1] https://github.com/feross/clipboard-copy [2] https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API PR #22792.
This commit is contained in:
parent
4b07597d54
commit
96f0eebc4e
11 changed files with 123 additions and 72 deletions
|
@ -31,7 +31,7 @@
|
|||
<script defer src="scripts/localpreferences.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/color-scheme.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/mocha-init.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script defer src="scripts/lib/clipboard.min.js"></script>
|
||||
<script defer src="scripts/lib/clipboard-copy.js"></script>
|
||||
<script defer src="scripts/filesystem.js?v=${CACHEID}"></script>
|
||||
<script defer src="scripts/misc.js?locale=${LANG}&v=${CACHEID}"></script>
|
||||
<script defer src="scripts/progressbar.js?v=${CACHEID}"></script>
|
||||
|
|
|
@ -1785,26 +1785,29 @@ window.addEventListener("DOMContentLoaded", (event) => {
|
|||
}
|
||||
});
|
||||
|
||||
new ClipboardJS(".copyToClipboard", {
|
||||
text: (trigger) => {
|
||||
switch (trigger.id) {
|
||||
case "copyName":
|
||||
return copyNameFN();
|
||||
case "copyInfohash1":
|
||||
return copyInfohashFN(1);
|
||||
case "copyInfohash2":
|
||||
return copyInfohashFN(2);
|
||||
case "copyMagnetLink":
|
||||
return copyMagnetLinkFN();
|
||||
case "copyID":
|
||||
return copyIdFN();
|
||||
case "copyComment":
|
||||
return copyCommentFN();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
for (const element of document.getElementsByClassName("copyToClipboard")) {
|
||||
const setupClickEvent = (textFunc) => element.addEventListener("click", async (event) => await clipboardCopy(textFunc()));
|
||||
switch (element.id) {
|
||||
case "copyName":
|
||||
setupClickEvent(copyNameFN);
|
||||
break;
|
||||
case "copyInfohash1":
|
||||
setupClickEvent(() => copyInfohashFN(1));
|
||||
break;
|
||||
case "copyInfohash2":
|
||||
setupClickEvent(() => copyInfohashFN(2));
|
||||
break;
|
||||
case "copyMagnetLink":
|
||||
setupClickEvent(copyMagnetLinkFN);
|
||||
break;
|
||||
case "copyID":
|
||||
setupClickEvent(copyIdFN);
|
||||
break;
|
||||
case "copyComment":
|
||||
setupClickEvent(copyCommentFN);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener("visibilitychange", (event) => {
|
||||
if (document.hidden)
|
||||
|
|
63
src/webui/www/private/scripts/lib/clipboard-copy.js
Normal file
63
src/webui/www/private/scripts/lib/clipboard-copy.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*! clipboard-copy. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
/* global DOMException */
|
||||
|
||||
//module.exports = clipboardCopy
|
||||
|
||||
function makeError () {
|
||||
return new DOMException('The request is not allowed', 'NotAllowedError')
|
||||
}
|
||||
|
||||
async function copyClipboardApi (text) {
|
||||
// Use the Async Clipboard API when available. Requires a secure browsing
|
||||
// context (i.e. HTTPS)
|
||||
if (!navigator.clipboard) {
|
||||
throw makeError()
|
||||
}
|
||||
return navigator.clipboard.writeText(text)
|
||||
}
|
||||
|
||||
async function copyExecCommand (text) {
|
||||
// Put the text to copy into a <span>
|
||||
const span = document.createElement('span')
|
||||
span.textContent = text
|
||||
|
||||
// Preserve consecutive spaces and newlines
|
||||
span.style.whiteSpace = 'pre'
|
||||
span.style.webkitUserSelect = 'auto'
|
||||
span.style.userSelect = 'all'
|
||||
|
||||
// Add the <span> to the page
|
||||
document.body.appendChild(span)
|
||||
|
||||
// Make a selection object representing the range of text selected by the user
|
||||
const selection = window.getSelection()
|
||||
const range = window.document.createRange()
|
||||
selection.removeAllRanges()
|
||||
range.selectNode(span)
|
||||
selection.addRange(range)
|
||||
|
||||
// Copy text to the clipboard
|
||||
let success = false
|
||||
try {
|
||||
success = window.document.execCommand('copy')
|
||||
} finally {
|
||||
// Cleanup
|
||||
selection.removeAllRanges()
|
||||
window.document.body.removeChild(span)
|
||||
}
|
||||
|
||||
if (!success) throw makeError()
|
||||
}
|
||||
|
||||
async function clipboardCopy (text) {
|
||||
try {
|
||||
await copyClipboardApi(text)
|
||||
} catch (err) {
|
||||
// ...Otherwise, use document.execCommand() fallback
|
||||
try {
|
||||
await copyExecCommand(text)
|
||||
} catch (err2) {
|
||||
throw (err2 || err || makeError())
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -183,10 +183,9 @@ window.qBittorrent.PropPeers ??= (() => {
|
|||
}
|
||||
});
|
||||
|
||||
new ClipboardJS("#CopyPeerInfo", {
|
||||
text: (trigger) => {
|
||||
return torrentPeersTable.selectedRowsIds().join("\n");
|
||||
}
|
||||
document.getElementById("CopyPeerInfo").addEventListener("click", async (event) => {
|
||||
const text = torrentPeersTable.selectedRowsIds().join("\n");
|
||||
await clipboardCopy(text);
|
||||
});
|
||||
|
||||
torrentPeersTable.setup("torrentPeersTableDiv", "torrentPeersTableFixedHeaderDiv", torrentPeersContextMenu, true);
|
||||
|
|
|
@ -248,10 +248,9 @@ window.qBittorrent.PropTrackers ??= (() => {
|
|||
torrentTrackersTable.clear();
|
||||
};
|
||||
|
||||
new ClipboardJS("#CopyTrackerUrl", {
|
||||
text: (trigger) => {
|
||||
return torrentTrackersTable.selectedRowsIds().join("\n");
|
||||
}
|
||||
document.getElementById("CopyTrackerUrl").addEventListener("click", async (event) => {
|
||||
const text = torrentTrackersTable.selectedRowsIds().join("\n");
|
||||
await clipboardCopy(text);
|
||||
});
|
||||
|
||||
torrentTrackersTable.setup("torrentTrackersTableDiv", "torrentTrackersTableFixedHeaderDiv", torrentTrackersContextMenu, true);
|
||||
|
|
|
@ -219,10 +219,9 @@ window.qBittorrent.PropWebseeds ??= (() => {
|
|||
torrentWebseedsTable.clear();
|
||||
};
|
||||
|
||||
new ClipboardJS("#CopyWebseedUrl", {
|
||||
text: (trigger) => {
|
||||
return torrentWebseedsTable.selectedRowsIds().join("\n");
|
||||
}
|
||||
document.getElementById("CopyWebseedUrl").addEventListener("click", async (event) => {
|
||||
const text = torrentWebseedsTable.selectedRowsIds().join("\n");
|
||||
await clipboardCopy(text);
|
||||
});
|
||||
|
||||
torrentWebseedsTable.setup("torrentWebseedsTableDiv", "torrentWebseedsTableFixedHeaderDiv", torrentWebseedsContextMenu, true);
|
||||
|
|
|
@ -866,20 +866,20 @@ window.qBittorrent.Search ??= (() => {
|
|||
state.loadResultsTimer = loadSearchResultsData.delay(500, this, searchId);
|
||||
};
|
||||
|
||||
new ClipboardJS(".copySearchDataToClipboard", {
|
||||
text: (trigger) => {
|
||||
switch (trigger.id) {
|
||||
case "copySearchTorrentName":
|
||||
return copySearchTorrentName();
|
||||
case "copySearchTorrentDownloadLink":
|
||||
return copySearchTorrentDownloadLink();
|
||||
case "copySearchTorrentDescriptionUrl":
|
||||
return copySearchTorrentDescriptionUrl();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
for (const element of document.getElementsByClassName("copySearchDataToClipboard")) {
|
||||
const setupClickEvent = (textFunc) => element.addEventListener("click", async (event) => await clipboardCopy(textFunc()));
|
||||
switch (element.id) {
|
||||
case "copySearchTorrentName":
|
||||
setupClickEvent(copySearchTorrentName);
|
||||
break;
|
||||
case "copySearchTorrentDownloadLink":
|
||||
setupClickEvent(copySearchTorrentDownloadLink);
|
||||
break;
|
||||
case "copySearchTorrentDescriptionUrl":
|
||||
setupClickEvent(copySearchTorrentDescriptionUrl);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return exports();
|
||||
})();
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
</div>
|
||||
|
||||
<ul id="logTableMenu" class="contextMenu">
|
||||
<li><a href="#" class="copyLogDataToClipboard"><img src="images/edit-copy.svg" alt="QBT_TR(Copy)QBT_TR[CONTEXT=ExecutionLogWidget]">QBT_TR(Copy)QBT_TR[CONTEXT=ExecutionLogWidget]</a></li>
|
||||
<li><a href="#" id="copyLogDataToClipboard"><img src="images/edit-copy.svg" alt="QBT_TR(Copy)QBT_TR[CONTEXT=ExecutionLogWidget]">QBT_TR(Copy)QBT_TR[CONTEXT=ExecutionLogWidget]</a></li>
|
||||
<li><a href="#Clear"><img src="images/list-remove.svg" alt="QBT_TR(Clear)QBT_TR[CONTEXT=ExecutionLogWidget]">QBT_TR(Clear)QBT_TR[CONTEXT=ExecutionLogWidget]</a></li>
|
||||
</ul>
|
||||
|
||||
|
@ -418,15 +418,11 @@
|
|||
});
|
||||
};
|
||||
|
||||
new ClipboardJS(".copyLogDataToClipboard", {
|
||||
text: () => {
|
||||
const msg = [];
|
||||
tableInfo[currentSelectedTab].instance.selectedRowsIds().forEach((rowId) => {
|
||||
msg.push(tableInfo[currentSelectedTab].instance.getRow(rowId).full_data[(currentSelectedTab === "main") ? "message" : "ip"]);
|
||||
});
|
||||
|
||||
return msg.join("\n");
|
||||
}
|
||||
document.getElementById("copyLogDataToClipboard").addEventListener("click", async (event) => {
|
||||
const instance = tableInfo[currentSelectedTab].instance;
|
||||
const type = (currentSelectedTab === "main") ? "message" : "ip";
|
||||
const msg = instance.selectedRowsIds().map((rowId) => instance.getRow(rowId).full_data[type]);
|
||||
await clipboardCopy(msg.join("\n"));
|
||||
});
|
||||
|
||||
return exports();
|
||||
|
|
|
@ -277,17 +277,16 @@
|
|||
}
|
||||
});
|
||||
|
||||
new ClipboardJS("#CopyFeedURL", {
|
||||
text: () => {
|
||||
let joined = "";
|
||||
for (const rowID of rssFeedTable.selectedRows) {
|
||||
const row = rssFeedTable.getRow(rowID);
|
||||
if (row.full_data.dataUid !== "")
|
||||
joined += `${row.full_data.dataUrl}\n`;
|
||||
}
|
||||
return joined.slice(0, -1);
|
||||
document.getElementById("CopyFeedURL").addEventListener("click", async (event) => {
|
||||
let joined = "";
|
||||
for (const rowID of rssFeedTable.selectedRows) {
|
||||
const row = rssFeedTable.getRow(rowID);
|
||||
if (row.full_data.dataUid !== "")
|
||||
joined += `${row.full_data.dataUrl}\n`;
|
||||
}
|
||||
await clipboardCopy(joined.slice(0, -1));
|
||||
});
|
||||
|
||||
rssFeedTable.setup("rssFeedTableDiv", "rssFeedFixedHeaderDiv", rssFeedContextMenu);
|
||||
|
||||
const rssArticleContextMenu = new window.qBittorrent.ContextMenu.RssArticleContextMenu({
|
||||
|
|
|
@ -400,7 +400,7 @@
|
|||
<file>private/scripts/dynamicTable.js</file>
|
||||
<file>private/scripts/file-tree.js</file>
|
||||
<file>private/scripts/filesystem.js</file>
|
||||
<file>private/scripts/lib/clipboard.min.js</file>
|
||||
<file>private/scripts/lib/clipboard-copy.js</file>
|
||||
<file>private/scripts/lib/mocha.min.js</file>
|
||||
<file>private/scripts/lib/MooTools-Core-1.6.0-compat-compressed.js</file>
|
||||
<file>private/scripts/lib/MooTools-More-1.6.0-compat-compressed.js</file>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue