mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-23 17:59:44 +00:00
WebUI: fix 'rename files' dialog cannot be opened more than once
Some checks failed
CI - File health / Check (push) Has been cancelled
CI - macOS / Build (1.2.19, GUI=OFF, 6.7.0) (push) Has been cancelled
CI - macOS / Build (1.2.19, GUI=ON, 6.7.0) (push) Has been cancelled
CI - macOS / Build (2.0.10, GUI=OFF, 6.7.0) (push) Has been cancelled
CI - macOS / Build (2.0.10, GUI=ON, 6.7.0) (push) Has been cancelled
CI - Python / Check (push) Has been cancelled
CI - Ubuntu / Build (1.2.19, GUI=OFF, 6.5.2) (push) Has been cancelled
CI - Ubuntu / Build (1.2.19, GUI=ON, 6.5.2) (push) Has been cancelled
CI - Ubuntu / Build (2.0.10, GUI=OFF, 6.5.2) (push) Has been cancelled
CI - Ubuntu / Build (2.0.10, GUI=ON, 6.5.2) (push) Has been cancelled
CI - WebUI / Check (push) Has been cancelled
CI - Windows / Build (1.2.19) (push) Has been cancelled
CI - Windows / Build (2.0.10) (push) Has been cancelled
Some checks failed
CI - File health / Check (push) Has been cancelled
CI - macOS / Build (1.2.19, GUI=OFF, 6.7.0) (push) Has been cancelled
CI - macOS / Build (1.2.19, GUI=ON, 6.7.0) (push) Has been cancelled
CI - macOS / Build (2.0.10, GUI=OFF, 6.7.0) (push) Has been cancelled
CI - macOS / Build (2.0.10, GUI=ON, 6.7.0) (push) Has been cancelled
CI - Python / Check (push) Has been cancelled
CI - Ubuntu / Build (1.2.19, GUI=OFF, 6.5.2) (push) Has been cancelled
CI - Ubuntu / Build (1.2.19, GUI=ON, 6.5.2) (push) Has been cancelled
CI - Ubuntu / Build (2.0.10, GUI=OFF, 6.5.2) (push) Has been cancelled
CI - Ubuntu / Build (2.0.10, GUI=ON, 6.5.2) (push) Has been cancelled
CI - WebUI / Check (push) Has been cancelled
CI - Windows / Build (1.2.19) (push) Has been cancelled
CI - Windows / Build (2.0.10) (push) Has been cancelled
Added an IIFE around the whole script to suppress variable redeclaration errors. Closes #21614. Original PR #21620. PR #21621.
This commit is contained in:
parent
84372de675
commit
49f57b1049
@ -14,15 +14,13 @@
|
|||||||
<script>
|
<script>
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
if (window.parent.qBittorrent !== undefined)
|
(() => {
|
||||||
|
if (window.parent.qBittorrent !== undefined)
|
||||||
|
window.qBittorrent = window.parent.qBittorrent;
|
||||||
window.qBittorrent = window.parent.qBittorrent;
|
window.qBittorrent = window.parent.qBittorrent;
|
||||||
window.qBittorrent = window.parent.qBittorrent;
|
|
||||||
|
|
||||||
const TriState = window.qBittorrent.FileTree.TriState;
|
const data = window.MUI.Windows.instances["multiRenamePage"].options.data;
|
||||||
const data = window.MUI.Windows.instances["multiRenamePage"].options.data;
|
const bulkRenameFilesContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
|
||||||
let bulkRenameFilesContextMenu;
|
|
||||||
if (!bulkRenameFilesContextMenu) {
|
|
||||||
bulkRenameFilesContextMenu = new window.qBittorrent.ContextMenu.ContextMenu({
|
|
||||||
targets: "#bulkRenameFilesTableDiv tr",
|
targets: "#bulkRenameFilesTableDiv tr",
|
||||||
menu: "multiRenameFilesMenu",
|
menu: "multiRenameFilesMenu",
|
||||||
actions: {
|
actions: {
|
||||||
@ -40,36 +38,30 @@
|
|||||||
y: 2
|
y: 2
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the dynamic table for bulk renaming
|
// Setup the dynamic table for bulk renaming
|
||||||
const bulkRenameFilesTable = new window.qBittorrent.DynamicTable.BulkRenameTorrentFilesTable();
|
const bulkRenameFilesTable = new window.qBittorrent.DynamicTable.BulkRenameTorrentFilesTable();
|
||||||
bulkRenameFilesTable.setup("bulkRenameFilesTableDiv", "bulkRenameFilesTableFixedHeaderDiv", bulkRenameFilesContextMenu);
|
bulkRenameFilesTable.setup("bulkRenameFilesTableDiv", "bulkRenameFilesTableFixedHeaderDiv", bulkRenameFilesContextMenu);
|
||||||
|
|
||||||
// Inject checkbox into the first column of the table header
|
// Inject checkbox into the first column of the table header
|
||||||
const tableHeaders = $$("#bulkRenameFilesTableFixedHeaderDiv .dynamicTableHeader th");
|
const tableHeaders = $$("#bulkRenameFilesTableFixedHeaderDiv .dynamicTableHeader th");
|
||||||
let checkboxHeader;
|
if (tableHeaders.length > 0) {
|
||||||
if (tableHeaders.length > 0) {
|
const checkboxHeader = new Element("input");
|
||||||
if (checkboxHeader)
|
checkboxHeader.set("type", "checkbox");
|
||||||
checkboxHeader.remove();
|
checkboxHeader.set("id", "rootMultiRename_cb");
|
||||||
checkboxHeader = new Element("input");
|
checkboxHeader.addEvent("click", (e) => {
|
||||||
checkboxHeader.set("type", "checkbox");
|
bulkRenameFilesTable.toggleGlobalCheckbox();
|
||||||
checkboxHeader.set("id", "rootMultiRename_cb");
|
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
||||||
checkboxHeader.addEvent("click", (e) => {
|
fileRenamer.update();
|
||||||
bulkRenameFilesTable.toggleGlobalCheckbox();
|
});
|
||||||
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
const checkboxTH = tableHeaders[0];
|
const checkboxTH = tableHeaders[0];
|
||||||
checkboxHeader.injectInside(checkboxTH);
|
checkboxHeader.injectInside(checkboxTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register keyboard events to modal window
|
// Register keyboard events to modal window
|
||||||
// https://github.com/qbittorrent/qBittorrent/pull/18687#discussion_r1135045726
|
// https://github.com/qbittorrent/qBittorrent/pull/18687#discussion_r1135045726
|
||||||
let keyboard;
|
const keyboard = new Keyboard({
|
||||||
if (!keyboard) {
|
|
||||||
keyboard = new Keyboard({
|
|
||||||
defaultEventType: "keydown",
|
defaultEventType: "keydown",
|
||||||
events: {
|
events: {
|
||||||
"Escape": function(event) {
|
"Escape": function(event) {
|
||||||
@ -83,326 +75,326 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
keyboard.activate();
|
keyboard.activate();
|
||||||
}
|
|
||||||
|
|
||||||
const fileRenamer = new window.qBittorrent.MultiRename.RenameFiles();
|
const fileRenamer = new window.qBittorrent.MultiRename.RenameFiles();
|
||||||
fileRenamer.hash = data.hash;
|
fileRenamer.hash = data.hash;
|
||||||
|
|
||||||
// Load Multi Rename Preferences
|
// Load Multi Rename Preferences
|
||||||
const multiRenamePrefChecked = LocalPreferences.get("multirename_rememberPreferences", "true") === "true";
|
const multiRenamePrefChecked = LocalPreferences.get("multirename_rememberPreferences", "true") === "true";
|
||||||
$("multirename_rememberprefs_checkbox").setProperty("checked", multiRenamePrefChecked);
|
$("multirename_rememberprefs_checkbox").setProperty("checked", multiRenamePrefChecked);
|
||||||
|
|
||||||
if (multiRenamePrefChecked) {
|
if (multiRenamePrefChecked) {
|
||||||
const multirename_search = LocalPreferences.get("multirename_search", "");
|
const multirename_search = LocalPreferences.get("multirename_search", "");
|
||||||
fileRenamer.setSearch(multirename_search);
|
fileRenamer.setSearch(multirename_search);
|
||||||
$("multiRenameSearch").set("value", multirename_search);
|
$("multiRenameSearch").set("value", multirename_search);
|
||||||
|
|
||||||
const multirename_useRegex = LocalPreferences.get("multirename_useRegex", false);
|
const multirename_useRegex = LocalPreferences.get("multirename_useRegex", false);
|
||||||
fileRenamer.useRegex = multirename_useRegex === "true";
|
fileRenamer.useRegex = multirename_useRegex === "true";
|
||||||
$("use_regex_search").checked = fileRenamer.useRegex;
|
$("use_regex_search").checked = fileRenamer.useRegex;
|
||||||
|
|
||||||
const multirename_matchAllOccurrences = LocalPreferences.get("multirename_matchAllOccurrences", false);
|
const multirename_matchAllOccurrences = LocalPreferences.get("multirename_matchAllOccurrences", false);
|
||||||
fileRenamer.matchAllOccurrences = multirename_matchAllOccurrences === "true";
|
fileRenamer.matchAllOccurrences = multirename_matchAllOccurrences === "true";
|
||||||
$("match_all_occurrences").checked = fileRenamer.matchAllOccurrences;
|
$("match_all_occurrences").checked = fileRenamer.matchAllOccurrences;
|
||||||
|
|
||||||
const multirename_caseSensitive = LocalPreferences.get("multirename_caseSensitive", false);
|
const multirename_caseSensitive = LocalPreferences.get("multirename_caseSensitive", false);
|
||||||
fileRenamer.caseSensitive = multirename_caseSensitive === "true";
|
fileRenamer.caseSensitive = multirename_caseSensitive === "true";
|
||||||
$("case_sensitive").checked = fileRenamer.caseSensitive;
|
$("case_sensitive").checked = fileRenamer.caseSensitive;
|
||||||
|
|
||||||
const multirename_replace = LocalPreferences.get("multirename_replace", "");
|
const multirename_replace = LocalPreferences.get("multirename_replace", "");
|
||||||
fileRenamer.setReplacement(multirename_replace);
|
fileRenamer.setReplacement(multirename_replace);
|
||||||
$("multiRenameReplace").set("value", multirename_replace);
|
$("multiRenameReplace").set("value", multirename_replace);
|
||||||
|
|
||||||
const multirename_appliesTo = LocalPreferences.get("multirename_appliesTo", window.qBittorrent.MultiRename.AppliesTo.FilenameExtension);
|
const multirename_appliesTo = LocalPreferences.get("multirename_appliesTo", window.qBittorrent.MultiRename.AppliesTo.FilenameExtension);
|
||||||
fileRenamer.appliesTo = window.qBittorrent.MultiRename.AppliesTo[multirename_appliesTo];
|
fileRenamer.appliesTo = window.qBittorrent.MultiRename.AppliesTo[multirename_appliesTo];
|
||||||
$("applies_to_option").set("value", fileRenamer.appliesTo);
|
$("applies_to_option").set("value", fileRenamer.appliesTo);
|
||||||
|
|
||||||
const multirename_includeFiles = LocalPreferences.get("multirename_includeFiles", true);
|
const multirename_includeFiles = LocalPreferences.get("multirename_includeFiles", true);
|
||||||
fileRenamer.includeFiles = multirename_includeFiles === "true";
|
fileRenamer.includeFiles = multirename_includeFiles === "true";
|
||||||
$("include_files").checked = fileRenamer.includeFiles;
|
$("include_files").checked = fileRenamer.includeFiles;
|
||||||
|
|
||||||
const multirename_includeFolders = LocalPreferences.get("multirename_includeFolders", false);
|
const multirename_includeFolders = LocalPreferences.get("multirename_includeFolders", false);
|
||||||
fileRenamer.includeFolders = multirename_includeFolders === "true";
|
fileRenamer.includeFolders = multirename_includeFolders === "true";
|
||||||
$("include_folders").checked = fileRenamer.includeFolders;
|
$("include_folders").checked = fileRenamer.includeFolders;
|
||||||
|
|
||||||
const multirename_fileEnumerationStart = LocalPreferences.get("multirename_fileEnumerationStart", 0);
|
const multirename_fileEnumerationStart = LocalPreferences.get("multirename_fileEnumerationStart", 0);
|
||||||
fileRenamer.fileEnumerationStart = parseInt(multirename_fileEnumerationStart, 10);
|
fileRenamer.fileEnumerationStart = parseInt(multirename_fileEnumerationStart, 10);
|
||||||
$("file_counter").set("value", fileRenamer.fileEnumerationStart);
|
|
||||||
|
|
||||||
const multirename_replaceAll = LocalPreferences.get("multirename_replaceAll", false);
|
|
||||||
fileRenamer.replaceAll = multirename_replaceAll === "true";
|
|
||||||
const renameButtonValue = fileRenamer.replaceAll ? "Replace All" : "Replace";
|
|
||||||
$("renameOptions").set("value", renameButtonValue);
|
|
||||||
$("renameButton").set("value", renameButtonValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fires every time a row's selection changes
|
|
||||||
bulkRenameFilesTable.onRowSelectionChange = function(row) {
|
|
||||||
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
|
||||||
fileRenamer.update();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup Search Events that control renaming
|
|
||||||
$("multiRenameSearch").addEvent("input", (e) => {
|
|
||||||
const sanitized = e.target.value.replace(/\n/g, "");
|
|
||||||
$("multiRenameSearch").set("value", sanitized);
|
|
||||||
|
|
||||||
// Search input has changed
|
|
||||||
$("multiRenameSearch").style["border-color"] = "";
|
|
||||||
LocalPreferences.set("multirename_search", sanitized);
|
|
||||||
fileRenamer.setSearch(sanitized);
|
|
||||||
});
|
|
||||||
$("use_regex_search").addEvent("change", (e) => {
|
|
||||||
fileRenamer.useRegex = e.target.checked;
|
|
||||||
LocalPreferences.set("multirename_useRegex", e.target.checked);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
$("match_all_occurrences").addEvent("change", (e) => {
|
|
||||||
fileRenamer.matchAllOccurrences = e.target.checked;
|
|
||||||
LocalPreferences.set("multirename_matchAllOccurrences", e.target.checked);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
$("case_sensitive").addEvent("change", (e) => {
|
|
||||||
fileRenamer.caseSensitive = e.target.checked;
|
|
||||||
LocalPreferences.set("multirename_caseSensitive", e.target.checked);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fires every time the filerenamer gets changed, it will update all the rows in the table
|
|
||||||
*/
|
|
||||||
fileRenamer.onChanged = function(matchedRows) {
|
|
||||||
// Clear renamed column
|
|
||||||
document
|
|
||||||
.querySelectorAll("span[id^='filesTablefileRenamed']")
|
|
||||||
.forEach((span) => {
|
|
||||||
span.set("text", "");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update renamed column for matched rows
|
|
||||||
for (let i = 0; i < matchedRows.length; ++i) {
|
|
||||||
const row = matchedRows[i];
|
|
||||||
$("filesTablefileRenamed" + row.rowId).set("text", row.renamed);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fileRenamer.onInvalidRegex = function(err) {
|
|
||||||
$("multiRenameSearch").style["border-color"] = "#CC0033";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup Replace Events that control renaming
|
|
||||||
$("multiRenameReplace").addEvent("input", (e) => {
|
|
||||||
const sanitized = e.target.value.replace(/\n/g, "");
|
|
||||||
$("multiRenameReplace").set("value", sanitized);
|
|
||||||
|
|
||||||
// Replace input has changed
|
|
||||||
$("multiRenameReplace").style["border-color"] = "";
|
|
||||||
LocalPreferences.set("multirename_replace", sanitized);
|
|
||||||
fileRenamer.setReplacement(sanitized);
|
|
||||||
});
|
|
||||||
$("applies_to_option").addEvent("change", (e) => {
|
|
||||||
fileRenamer.appliesTo = e.target.value;
|
|
||||||
LocalPreferences.set("multirename_appliesTo", e.target.value);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
$("include_files").addEvent("change", (e) => {
|
|
||||||
fileRenamer.includeFiles = e.target.checked;
|
|
||||||
LocalPreferences.set("multirename_includeFiles", e.target.checked);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
$("include_folders").addEvent("change", (e) => {
|
|
||||||
fileRenamer.includeFolders = e.target.checked;
|
|
||||||
LocalPreferences.set("multirename_includeFolders", e.target.checked);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
$("file_counter").addEvent("input", (e) => {
|
|
||||||
let value = e.target.valueAsNumber;
|
|
||||||
if (!value)
|
|
||||||
value = 0;
|
|
||||||
if (value < 0)
|
|
||||||
value = 0;
|
|
||||||
if (value > 99999999)
|
|
||||||
value = 99999999;
|
|
||||||
fileRenamer.fileEnumerationStart = value;
|
|
||||||
$("file_counter").set("value", value);
|
|
||||||
LocalPreferences.set("multirename_fileEnumerationStart", value);
|
|
||||||
fileRenamer.update();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Setup Rename Operation Events
|
|
||||||
$("renameButton").addEvent("click", (e) => {
|
|
||||||
// Disable Search Options
|
|
||||||
$("multiRenameSearch").disabled = true;
|
|
||||||
$("use_regex_search").disabled = true;
|
|
||||||
$("match_all_occurrences").disabled = true;
|
|
||||||
$("case_sensitive").disabled = true;
|
|
||||||
// Disable Replace Options
|
|
||||||
$("multiRenameReplace").disabled = true;
|
|
||||||
$("applies_to_option").disabled = true;
|
|
||||||
$("include_files").disabled = true;
|
|
||||||
$("include_folders").disabled = true;
|
|
||||||
$("file_counter").disabled = true;
|
|
||||||
// Disable Rename Buttons
|
|
||||||
$("renameButton").disabled = true;
|
|
||||||
$("renameOptions").disabled = true;
|
|
||||||
// Clear error text
|
|
||||||
$("rename_error").set("text", "");
|
|
||||||
fileRenamer.rename();
|
|
||||||
});
|
|
||||||
fileRenamer.onRenamed = function(rows) {
|
|
||||||
// Disable Search Options
|
|
||||||
$("multiRenameSearch").disabled = false;
|
|
||||||
$("use_regex_search").disabled = false;
|
|
||||||
$("match_all_occurrences").disabled = false;
|
|
||||||
$("case_sensitive").disabled = false;
|
|
||||||
// Disable Replace Options
|
|
||||||
$("multiRenameReplace").disabled = false;
|
|
||||||
$("applies_to_option").disabled = false;
|
|
||||||
$("include_files").disabled = false;
|
|
||||||
$("include_folders").disabled = false;
|
|
||||||
$("file_counter").disabled = false;
|
|
||||||
// Disable Rename Buttons
|
|
||||||
$("renameButton").disabled = false;
|
|
||||||
$("renameOptions").disabled = false;
|
|
||||||
|
|
||||||
// Recreate table
|
|
||||||
let selectedRows = bulkRenameFilesTable.getSelectedRows().map(row => row.rowId.toString());
|
|
||||||
for (const renamedRow of rows)
|
|
||||||
selectedRows = selectedRows.filter(selectedRow => selectedRow !== renamedRow.rowId.toString());
|
|
||||||
bulkRenameFilesTable.clear();
|
|
||||||
|
|
||||||
// Adjust file enumeration count by 1 when replacing single files to prevent naming conflicts
|
|
||||||
if (!fileRenamer.replaceAll) {
|
|
||||||
fileRenamer.fileEnumerationStart++;
|
|
||||||
$("file_counter").set("value", fileRenamer.fileEnumerationStart);
|
$("file_counter").set("value", fileRenamer.fileEnumerationStart);
|
||||||
|
|
||||||
|
const multirename_replaceAll = LocalPreferences.get("multirename_replaceAll", false);
|
||||||
|
fileRenamer.replaceAll = multirename_replaceAll === "true";
|
||||||
|
const renameButtonValue = fileRenamer.replaceAll ? "Replace All" : "Replace";
|
||||||
|
$("renameOptions").set("value", renameButtonValue);
|
||||||
|
$("renameButton").set("value", renameButtonValue);
|
||||||
}
|
}
|
||||||
setupTable(selectedRows);
|
|
||||||
};
|
|
||||||
fileRenamer.onRenameError = function(err, row) {
|
|
||||||
if (err.xhr.status === 409)
|
|
||||||
$("rename_error").set("text", `QBT_TR(Rename failed: file or folder already exists)QBT_TR[CONTEXT=PropertiesWidget] \`${row.renamed}\``);
|
|
||||||
};
|
|
||||||
$("renameOptions").addEvent("change", (e) => {
|
|
||||||
const combobox = e.target;
|
|
||||||
const replaceOperation = combobox.value;
|
|
||||||
if (replaceOperation === "Replace")
|
|
||||||
fileRenamer.replaceAll = false;
|
|
||||||
else if (replaceOperation === "Replace All")
|
|
||||||
fileRenamer.replaceAll = true;
|
|
||||||
else
|
|
||||||
fileRenamer.replaceAll = false;
|
|
||||||
LocalPreferences.set("multirename_replaceAll", fileRenamer.replaceAll);
|
|
||||||
$("renameButton").set("value", replaceOperation);
|
|
||||||
});
|
|
||||||
$("closeButton").addEvent("click", () => {
|
|
||||||
window.parent.qBittorrent.Client.closeWindows();
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
// synchronize header scrolling to table body
|
|
||||||
$("bulkRenameFilesTableDiv").onscroll = function() {
|
|
||||||
const length = $(this).scrollLeft;
|
|
||||||
$("bulkRenameFilesTableFixedHeaderDiv").scrollLeft = length;
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTorrentFiles = function(files, selectedRows) {
|
// Fires every time a row's selection changes
|
||||||
const rows = files.map((file, index) => {
|
bulkRenameFilesTable.onRowSelectionChange = function(row) {
|
||||||
|
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
||||||
|
fileRenamer.update();
|
||||||
|
};
|
||||||
|
|
||||||
const row = {
|
// Setup Search Events that control renaming
|
||||||
fileId: index,
|
$("multiRenameSearch").addEvent("input", (e) => {
|
||||||
checked: 1, // unchecked
|
const sanitized = e.target.value.replace(/\n/g, "");
|
||||||
path: file.name,
|
$("multiRenameSearch").set("value", sanitized);
|
||||||
original: window.qBittorrent.Filesystem.fileName(file.name),
|
|
||||||
renamed: "",
|
|
||||||
size: file.size
|
|
||||||
};
|
|
||||||
|
|
||||||
return row;
|
// Search input has changed
|
||||||
|
$("multiRenameSearch").style["border-color"] = "";
|
||||||
|
LocalPreferences.set("multirename_search", sanitized);
|
||||||
|
fileRenamer.setSearch(sanitized);
|
||||||
|
});
|
||||||
|
$("use_regex_search").addEvent("change", (e) => {
|
||||||
|
fileRenamer.useRegex = e.target.checked;
|
||||||
|
LocalPreferences.set("multirename_useRegex", e.target.checked);
|
||||||
|
fileRenamer.update();
|
||||||
|
});
|
||||||
|
$("match_all_occurrences").addEvent("change", (e) => {
|
||||||
|
fileRenamer.matchAllOccurrences = e.target.checked;
|
||||||
|
LocalPreferences.set("multirename_matchAllOccurrences", e.target.checked);
|
||||||
|
fileRenamer.update();
|
||||||
|
});
|
||||||
|
$("case_sensitive").addEvent("change", (e) => {
|
||||||
|
fileRenamer.caseSensitive = e.target.checked;
|
||||||
|
LocalPreferences.set("multirename_caseSensitive", e.target.checked);
|
||||||
|
fileRenamer.update();
|
||||||
});
|
});
|
||||||
|
|
||||||
addRowsToTable(rows, selectedRows);
|
/**
|
||||||
};
|
* Fires every time the filerenamer gets changed, it will update all the rows in the table
|
||||||
|
*/
|
||||||
|
fileRenamer.onChanged = function(matchedRows) {
|
||||||
|
// Clear renamed column
|
||||||
|
document
|
||||||
|
.querySelectorAll("span[id^='filesTablefileRenamed']")
|
||||||
|
.forEach((span) => {
|
||||||
|
span.set("text", "");
|
||||||
|
});
|
||||||
|
|
||||||
const addRowsToTable = function(rows, selectedRows) {
|
// Update renamed column for matched rows
|
||||||
let rowId = 0;
|
for (let i = 0; i < matchedRows.length; ++i) {
|
||||||
const rootNode = new window.qBittorrent.FileTree.FolderNode();
|
const row = matchedRows[i];
|
||||||
rootNode.autoCheckFolders = false;
|
$("filesTablefileRenamed" + row.rowId).set("text", row.renamed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fileRenamer.onInvalidRegex = function(err) {
|
||||||
|
$("multiRenameSearch").style["border-color"] = "#CC0033";
|
||||||
|
};
|
||||||
|
|
||||||
rows.forEach((row) => {
|
// Setup Replace Events that control renaming
|
||||||
const pathItems = row.path.split(window.qBittorrent.Filesystem.PathSeparator);
|
$("multiRenameReplace").addEvent("input", (e) => {
|
||||||
|
const sanitized = e.target.value.replace(/\n/g, "");
|
||||||
|
$("multiRenameReplace").set("value", sanitized);
|
||||||
|
|
||||||
pathItems.pop(); // remove last item (i.e. file name)
|
// Replace input has changed
|
||||||
let parent = rootNode;
|
$("multiRenameReplace").style["border-color"] = "";
|
||||||
pathItems.forEach((folderName) => {
|
LocalPreferences.set("multirename_replace", sanitized);
|
||||||
if (folderName === ".unwanted")
|
fileRenamer.setReplacement(sanitized);
|
||||||
return;
|
});
|
||||||
|
$("applies_to_option").addEvent("change", (e) => {
|
||||||
|
fileRenamer.appliesTo = e.target.value;
|
||||||
|
LocalPreferences.set("multirename_appliesTo", e.target.value);
|
||||||
|
fileRenamer.update();
|
||||||
|
});
|
||||||
|
$("include_files").addEvent("change", (e) => {
|
||||||
|
fileRenamer.includeFiles = e.target.checked;
|
||||||
|
LocalPreferences.set("multirename_includeFiles", e.target.checked);
|
||||||
|
fileRenamer.update();
|
||||||
|
});
|
||||||
|
$("include_folders").addEvent("change", (e) => {
|
||||||
|
fileRenamer.includeFolders = e.target.checked;
|
||||||
|
LocalPreferences.set("multirename_includeFolders", e.target.checked);
|
||||||
|
fileRenamer.update();
|
||||||
|
});
|
||||||
|
$("file_counter").addEvent("input", (e) => {
|
||||||
|
let value = e.target.valueAsNumber;
|
||||||
|
if (!value)
|
||||||
|
value = 0;
|
||||||
|
if (value < 0)
|
||||||
|
value = 0;
|
||||||
|
if (value > 99999999)
|
||||||
|
value = 99999999;
|
||||||
|
fileRenamer.fileEnumerationStart = value;
|
||||||
|
$("file_counter").set("value", value);
|
||||||
|
LocalPreferences.set("multirename_fileEnumerationStart", value);
|
||||||
|
fileRenamer.update();
|
||||||
|
});
|
||||||
|
|
||||||
let folderNode = null;
|
// Setup Rename Operation Events
|
||||||
if (parent.children !== null) {
|
$("renameButton").addEvent("click", (e) => {
|
||||||
for (let i = 0; i < parent.children.length; ++i) {
|
// Disable Search Options
|
||||||
const childFolder = parent.children[i];
|
$("multiRenameSearch").disabled = true;
|
||||||
if (childFolder.original === folderName) {
|
$("use_regex_search").disabled = true;
|
||||||
folderNode = childFolder;
|
$("match_all_occurrences").disabled = true;
|
||||||
break;
|
$("case_sensitive").disabled = true;
|
||||||
|
// Disable Replace Options
|
||||||
|
$("multiRenameReplace").disabled = true;
|
||||||
|
$("applies_to_option").disabled = true;
|
||||||
|
$("include_files").disabled = true;
|
||||||
|
$("include_folders").disabled = true;
|
||||||
|
$("file_counter").disabled = true;
|
||||||
|
// Disable Rename Buttons
|
||||||
|
$("renameButton").disabled = true;
|
||||||
|
$("renameOptions").disabled = true;
|
||||||
|
// Clear error text
|
||||||
|
$("rename_error").set("text", "");
|
||||||
|
fileRenamer.rename();
|
||||||
|
});
|
||||||
|
fileRenamer.onRenamed = function(rows) {
|
||||||
|
// Disable Search Options
|
||||||
|
$("multiRenameSearch").disabled = false;
|
||||||
|
$("use_regex_search").disabled = false;
|
||||||
|
$("match_all_occurrences").disabled = false;
|
||||||
|
$("case_sensitive").disabled = false;
|
||||||
|
// Disable Replace Options
|
||||||
|
$("multiRenameReplace").disabled = false;
|
||||||
|
$("applies_to_option").disabled = false;
|
||||||
|
$("include_files").disabled = false;
|
||||||
|
$("include_folders").disabled = false;
|
||||||
|
$("file_counter").disabled = false;
|
||||||
|
// Disable Rename Buttons
|
||||||
|
$("renameButton").disabled = false;
|
||||||
|
$("renameOptions").disabled = false;
|
||||||
|
|
||||||
|
// Recreate table
|
||||||
|
let selectedRows = bulkRenameFilesTable.getSelectedRows().map(row => row.rowId.toString());
|
||||||
|
for (const renamedRow of rows)
|
||||||
|
selectedRows = selectedRows.filter(selectedRow => selectedRow !== renamedRow.rowId.toString());
|
||||||
|
bulkRenameFilesTable.clear();
|
||||||
|
|
||||||
|
// Adjust file enumeration count by 1 when replacing single files to prevent naming conflicts
|
||||||
|
if (!fileRenamer.replaceAll) {
|
||||||
|
fileRenamer.fileEnumerationStart++;
|
||||||
|
$("file_counter").set("value", fileRenamer.fileEnumerationStart);
|
||||||
|
}
|
||||||
|
setupTable(selectedRows);
|
||||||
|
};
|
||||||
|
fileRenamer.onRenameError = function(err, row) {
|
||||||
|
if (err.xhr.status === 409)
|
||||||
|
$("rename_error").set("text", `QBT_TR(Rename failed: file or folder already exists)QBT_TR[CONTEXT=PropertiesWidget] \`${row.renamed}\``);
|
||||||
|
};
|
||||||
|
$("renameOptions").addEvent("change", (e) => {
|
||||||
|
const combobox = e.target;
|
||||||
|
const replaceOperation = combobox.value;
|
||||||
|
if (replaceOperation === "Replace")
|
||||||
|
fileRenamer.replaceAll = false;
|
||||||
|
else if (replaceOperation === "Replace All")
|
||||||
|
fileRenamer.replaceAll = true;
|
||||||
|
else
|
||||||
|
fileRenamer.replaceAll = false;
|
||||||
|
LocalPreferences.set("multirename_replaceAll", fileRenamer.replaceAll);
|
||||||
|
$("renameButton").set("value", replaceOperation);
|
||||||
|
});
|
||||||
|
$("closeButton").addEvent("click", () => {
|
||||||
|
window.parent.qBittorrent.Client.closeWindows();
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
// synchronize header scrolling to table body
|
||||||
|
$("bulkRenameFilesTableDiv").onscroll = function() {
|
||||||
|
const length = $(this).scrollLeft;
|
||||||
|
$("bulkRenameFilesTableFixedHeaderDiv").scrollLeft = length;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTorrentFiles = function(files, selectedRows) {
|
||||||
|
const rows = files.map((file, index) => {
|
||||||
|
|
||||||
|
const row = {
|
||||||
|
fileId: index,
|
||||||
|
checked: 1, // unchecked
|
||||||
|
path: file.name,
|
||||||
|
original: window.qBittorrent.Filesystem.fileName(file.name),
|
||||||
|
renamed: "",
|
||||||
|
size: file.size
|
||||||
|
};
|
||||||
|
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
|
||||||
|
addRowsToTable(rows, selectedRows);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addRowsToTable = function(rows, selectedRows) {
|
||||||
|
let rowId = 0;
|
||||||
|
const rootNode = new window.qBittorrent.FileTree.FolderNode();
|
||||||
|
rootNode.autoCheckFolders = false;
|
||||||
|
|
||||||
|
rows.forEach((row) => {
|
||||||
|
const pathItems = row.path.split(window.qBittorrent.Filesystem.PathSeparator);
|
||||||
|
|
||||||
|
pathItems.pop(); // remove last item (i.e. file name)
|
||||||
|
let parent = rootNode;
|
||||||
|
pathItems.forEach((folderName) => {
|
||||||
|
if (folderName === ".unwanted")
|
||||||
|
return;
|
||||||
|
|
||||||
|
let folderNode = null;
|
||||||
|
if (parent.children !== null) {
|
||||||
|
for (let i = 0; i < parent.children.length; ++i) {
|
||||||
|
const childFolder = parent.children[i];
|
||||||
|
if (childFolder.original === folderName) {
|
||||||
|
folderNode = childFolder;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (folderNode === null) {
|
if (folderNode === null) {
|
||||||
folderNode = new window.qBittorrent.FileTree.FolderNode();
|
folderNode = new window.qBittorrent.FileTree.FolderNode();
|
||||||
folderNode.autoCheckFolders = false;
|
folderNode.autoCheckFolders = false;
|
||||||
folderNode.rowId = rowId;
|
folderNode.rowId = rowId;
|
||||||
folderNode.path = (parent.path === "")
|
folderNode.path = (parent.path === "")
|
||||||
? folderName
|
? folderName
|
||||||
: [parent.path, folderName].join(window.qBittorrent.Filesystem.PathSeparator);
|
: [parent.path, folderName].join(window.qBittorrent.Filesystem.PathSeparator);
|
||||||
folderNode.checked = selectedRows.includes(rowId.toString()) ? 0 : 1;
|
folderNode.checked = selectedRows.includes(rowId.toString()) ? 0 : 1;
|
||||||
folderNode.original = folderName;
|
folderNode.original = folderName;
|
||||||
folderNode.renamed = "";
|
folderNode.renamed = "";
|
||||||
folderNode.root = parent;
|
folderNode.root = parent;
|
||||||
parent.addChild(folderNode);
|
parent.addChild(folderNode);
|
||||||
|
|
||||||
++rowId;
|
++rowId;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent = folderNode;
|
parent = folderNode;
|
||||||
|
});
|
||||||
|
|
||||||
|
const childNode = new window.qBittorrent.FileTree.FileNode();
|
||||||
|
childNode.rowId = rowId;
|
||||||
|
childNode.path = row.path;
|
||||||
|
childNode.checked = selectedRows.includes(rowId.toString()) ? 0 : 1;
|
||||||
|
childNode.original = row.original;
|
||||||
|
childNode.renamed = "";
|
||||||
|
childNode.root = parent;
|
||||||
|
childNode.data = row;
|
||||||
|
parent.addChild(childNode);
|
||||||
|
|
||||||
|
++rowId;
|
||||||
});
|
});
|
||||||
|
|
||||||
const childNode = new window.qBittorrent.FileTree.FileNode();
|
bulkRenameFilesTable.populateTable(rootNode);
|
||||||
childNode.rowId = rowId;
|
bulkRenameFilesTable.updateTable(false);
|
||||||
childNode.path = row.path;
|
bulkRenameFilesTable.altRow();
|
||||||
childNode.checked = selectedRows.includes(rowId.toString()) ? 0 : 1;
|
|
||||||
childNode.original = row.original;
|
|
||||||
childNode.renamed = "";
|
|
||||||
childNode.root = parent;
|
|
||||||
childNode.data = row;
|
|
||||||
parent.addChild(childNode);
|
|
||||||
|
|
||||||
++rowId;
|
if (selectedRows !== undefined)
|
||||||
});
|
bulkRenameFilesTable.reselectRows(selectedRows);
|
||||||
|
|
||||||
bulkRenameFilesTable.populateTable(rootNode);
|
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
||||||
bulkRenameFilesTable.updateTable(false);
|
fileRenamer.update();
|
||||||
bulkRenameFilesTable.altRow();
|
};
|
||||||
|
|
||||||
if (selectedRows !== undefined)
|
const setupTable = function(selectedRows) {
|
||||||
bulkRenameFilesTable.reselectRows(selectedRows);
|
new Request.JSON({
|
||||||
|
url: new URI("api/v2/torrents/files?hash=" + data.hash),
|
||||||
fileRenamer.selectedFiles = bulkRenameFilesTable.getSelectedRows();
|
noCache: true,
|
||||||
fileRenamer.update();
|
method: "get",
|
||||||
};
|
onSuccess: function(files) {
|
||||||
|
if (files.length === 0)
|
||||||
const setupTable = function(selectedRows) {
|
bulkRenameFilesTable.clear();
|
||||||
new Request.JSON({
|
else
|
||||||
url: new URI("api/v2/torrents/files?hash=" + data.hash),
|
handleTorrentFiles(files, selectedRows);
|
||||||
noCache: true,
|
}
|
||||||
method: "get",
|
}).send();
|
||||||
onSuccess: function(files) {
|
};
|
||||||
if (files.length === 0)
|
setupTable(data.selectedRows);
|
||||||
bulkRenameFilesTable.clear();
|
})();
|
||||||
else
|
|
||||||
handleTorrentFiles(files, selectedRows);
|
|
||||||
}
|
|
||||||
}).send();
|
|
||||||
};
|
|
||||||
setupTable(data.selectedRows);
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user