Merge pull request #22650 from Chocobo1/webui_file_tree

* WebUI: migrate 'file tree' class to JS native class
* WebUI: avoid double lookup
This commit is contained in:
Chocobo1 2025-05-05 15:48:24 +08:00 committed by GitHub
commit 0262faa915
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -56,51 +56,51 @@ window.qBittorrent.FileTree ??= (() => {
}; };
Object.freeze(TriState); Object.freeze(TriState);
const FileTree = new Class({ class FileTree {
root: null, #root = null;
nodeMap: {}, #nodeMap = {}; // Object with Number as keys is faster than anything
setRoot: function(root) { setRoot(root) {
this.root = root; this.#root = root;
this.generateNodeMap(root); this.#generateNodeMap(root);
if (this.root.isFolder) if (this.#root.isFolder)
this.root.calculateSize(); this.#root.calculateSize();
}, }
getRoot: function() { getRoot() {
return this.root; return this.#root;
}, }
generateNodeMap: function(root) { #generateNodeMap(root) {
const stack = [root]; const stack = [root];
while (stack.length > 0) { while (stack.length > 0) {
const node = stack.pop(); const node = stack.pop();
// don't store root node in map // don't store root node in map
if (node.root !== null) if (node.root !== null)
this.nodeMap[node.rowId] = node; this.#nodeMap[node.rowId] = node;
stack.push(...node.children); stack.push(...node.children);
} }
}, }
getNode: function(rowId) { getNode(rowId) {
return (this.nodeMap[rowId] === undefined) // TODO: enforce caller sites to pass `rowId` as number and not string
? null const value = this.#nodeMap[Number(rowId)];
: this.nodeMap[rowId]; return (value !== undefined) ? value : null;
}, }
getRowId: (node) => { getRowId(node) {
return node.rowId; return node.rowId;
}, }
/** /**
* Returns the nodes in DFS in-order * Returns the nodes in DFS in-order
*/ */
toArray: function() { toArray() {
const ret = []; const ret = [];
const stack = this.root.children.toReversed(); const stack = this.#root.children.toReversed();
while (stack.length > 0) { while (stack.length > 0) {
const node = stack.pop(); const node = stack.pop();
ret.push(node); ret.push(node);
@ -108,45 +108,40 @@ window.qBittorrent.FileTree ??= (() => {
} }
return ret; return ret;
} }
}); }
const FileNode = new Class({ class FileNode {
name: "", name = "";
path: "", path = "";
rowId: null, rowId = null;
size: 0, size = 0;
checked: TriState.Unchecked, checked = TriState.Unchecked;
remaining: 0, remaining = 0;
progress: 0, progress = 0;
priority: FilePriority.Normal, priority = FilePriority.Normal;
availability: 0, availability = 0;
depth: 0, depth = 0;
root: null, root = null;
data: null, data = null;
isFolder: false, isFolder = false;
children: [], children = [];
}); }
const FolderNode = new Class({
Extends: FileNode,
class FolderNode extends FileNode {
/** /**
* Will automatically tick the checkbox for a folder if all subfolders and files are also ticked * Will automatically tick the checkbox for a folder if all subfolders and files are also ticked
*/ */
autoCheckFolders: true, autoCheckFolders = true;
isFolder = true;
initialize: function() { addChild(node) {
this.isFolder = true;
},
addChild: function(node) {
this.children.push(node); this.children.push(node);
}, }
/** /**
* Calculate size of node and its children * Calculate size of node and its children
*/ */
calculateSize: function() { calculateSize() {
const stack = [this]; const stack = [this];
const visited = []; const visited = [];
@ -202,7 +197,7 @@ window.qBittorrent.FileTree ??= (() => {
stack.pop(); stack.pop();
} }
} }
}); }
return exports(); return exports();
})(); })();