-
Notifications
You must be signed in to change notification settings - Fork 86
Fix #2500: File Manager UI/UX improvements #2501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughAdds programmatic file-tree navigation and "Popular" destination tracking; switches URL decoding to rawurldecode; introduces dialog JS helpers and warnings; implements path-specific terminal startup; refactors rsync progress and job handling; adjusts templates, data-attribute encoding, and styling to support the new UI behaviors. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant UI as Browse.page (Client)
participant Tree as FileTree (Renderer)
participant API as Control (Backend)
participant Store as PopularDestinations (Storage)
User->>UI: type or pick destination / click Popular
UI->>UI: setupTargetNavigation() capture state
UI->>Tree: navigateFileTree(path)
Tree->>Tree: openFolderRecursive(...) expand/select nodes
Tree-->>UI: updated tree state/display
User->>UI: confirm copy/move
UI->>API: submit job (target)
API->>Store: updatePopularDestinations(target)
Store->>Store: read/modify/write JSON (flock)
Store-->>API: ack
API-->>UI: job result
sequenceDiagram
actor User
participant Tree as FileTree
participant Store as PopularDestinations
Tree->>Store: getPopularDestinations(limit)
Store->>Store: loadPopularDestinations() from JSON
Store-->>Tree: return top N paths
Tree->>Tree: render "Popular" section (data-path)
User->>Tree: click popular destination
Tree-->>Browse.page: emit navigation event
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📜 Recent review detailsConfiguration used: Repository UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🧰 Additional context used🧠 Learnings (10)📚 Learning: 2025-12-30T20:28:06.818ZApplied to files:
📚 Learning: 2025-09-05T19:26:36.587ZApplied to files:
📚 Learning: 2025-03-27T22:04:34.550ZApplied to files:
📚 Learning: 2025-05-31T00:04:34.204ZApplied to files:
📚 Learning: 2025-08-13T03:13:53.283ZApplied to files:
📚 Learning: 2025-06-21T00:10:40.789ZApplied to files:
📚 Learning: 2025-06-03T21:27:15.912ZApplied to files:
📚 Learning: 2025-05-28T20:54:31.390ZApplied to files:
📚 Learning: 2025-07-11T17:24:33.977ZApplied to files:
📚 Learning: 2025-08-13T02:06:47.712ZApplied to files:
🔇 Additional comments (15)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔧 PR Test Plugin AvailableA test plugin has been generated for this PR that includes the modified files. Version: 📥 Installation Instructions:Install via Unraid Web UI:
Alternative: Direct Download
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
43-46: Consider adding error handling and file locking.The
file_put_contentscall lacks error handling and file locking. In a multi-tab or concurrent scenario, simultaneous writes could corrupt the JSON file.🔎 Proposed improvement with locking
function savePopularDestinations($data) { $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); - file_put_contents(POPULAR_DESTINATIONS_FILE, $json); + file_put_contents(POPULAR_DESTINATIONS_FILE, $json, LOCK_EX); }emhttp/plugins/dynamix/include/Control.php (1)
184-199: Potential index issue when undoing multiple jobs.When undoing multiple jobs (e.g., rows 1 and 3), the
unset()operations work correctly since they operate on the original array indices before removing any elements. However, afterunset(),implode("\n", $lines)will preserve gaps. Thearray_values()reindex is missing but not strictly needed since file_put_contents will join the remaining values correctly.The
array_reverseis unnecessary here since we're using direct array indices rather than sequential removal.🔎 Simplified version
case 'undo': $jobs = '/var/tmp/file.manager.jobs'; $undo = '0'; if (file_exists($jobs)) { - $rows = array_reverse(explode(',',$_POST['row'])); + $rows = explode(',',$_POST['row']); $lines = file($jobs, FILE_IGNORE_NEW_LINES); foreach ($rows as $row) { $line_number = $row - 1; // Convert 1-based job number to 0-based array index if (isset($lines[$line_number])) { unset($lines[$line_number]); } } + $lines = array_values($lines); // Re-index to remove gaps if (count($lines) > 0) { file_put_contents($jobs, implode("\n", $lines)."\n"); $undo = '2'; } else { delete_file($jobs); $undo = '1'; } } die($undo);
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/include/local_prepend.phpemhttp/plugins/dynamix/nchan/file_manageremhttp/plugins/dynamix/sheets/BrowseButton.cssemhttp/plugins/dynamix/styles/default-base.cssemhttp/plugins/dynamix/styles/default-dynamix.cssetc/rc.d/rc.nginx
💤 Files with no reviewable changes (2)
- emhttp/plugins/dynamix/sheets/BrowseButton.css
- emhttp/plugins/dynamix/styles/default-dynamix.css
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/local_prepend.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/Browse.php
📚 Learning: 2025-06-18T17:09:35.579Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2264
File: emhttp/plugins/dynamix/include/.login.php:0-0
Timestamp: 2025-06-18T17:09:35.579Z
Learning: In the Unraid webGUI login system (emhttp/plugins/dynamix/include/.login.php), the cooldown timer restarting on page reload during the cooldown period is intentional behavior, not a bug. When a form is resubmitted during cooldown, the timer should restart to provide consistent user feedback.
Applied to files:
emhttp/plugins/dynamix/include/local_prepend.php
📚 Learning: 2025-09-05T16:33:12.970Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2353
File: emhttp/plugins/dynamix/DashStats.page:2257-2257
Timestamp: 2025-09-05T16:33:12.970Z
Learning: In the Unraid webGUI Nchan system, the Nchan header declaration lists publisher scripts to start (e.g., "update_1"), while the JavaScript subscription endpoints use normalized names (e.g., "/sub/update1"). The publisher script "update_1" publishes to "/pub/update1" endpoint, creating a separation between script names and published endpoints. This is by design and not a mismatch.
Applied to files:
etc/rc.d/rc.nginx
📚 Learning: 2025-10-03T02:57:29.994Z
Learnt from: ljm42
Repo: unraid/webgui PR: 2414
File: etc/rc.d/rc.nginx:374-376
Timestamp: 2025-10-03T02:57:29.994Z
Learning: Repo unraid/webgui: In etc/rc.d/rc.nginx, maintainers prefer not to add explicit mv-failure checks or EXIT trap clearing around atomic writes in build_servers(), build_locations(), and build_ini(); treat mv failures (e.g., disk full/permissions) as non-recoverable and keep the implementation simple.
Applied to files:
etc/rc.d/rc.nginx
📚 Learning: 2025-09-05T16:33:12.970Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2353
File: emhttp/plugins/dynamix/DashStats.page:2257-2257
Timestamp: 2025-09-05T16:33:12.970Z
Learning: In the Unraid webGUI Nchan system, publisher scripts (like "update_1") publish to normalized endpoint names (like "update1"). The Nchan header lists the script names to start, while JavaScript subscribes to the published endpoints. For example: Nchan="update_1" starts the script which calls publish_noDupe('update1', data), and JavaScript subscribes to '/sub/update1'. This is the intended design, not a mismatch.
Applied to files:
etc/rc.d/rc.nginx
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/include/Templates.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Templates.php
🧬 Code graph analysis (3)
emhttp/plugins/dynamix/include/FileTree.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
getPopularDestinations(123-138)
emhttp/plugins/dynamix/include/Templates.php (1)
emhttp/plugins/dynamix/include/Helpers.php (1)
mk_option(182-184)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(52-116)
🔇 Additional comments (29)
etc/rc.d/rc.nginx (1)
415-415: Fix nchan subscriber endpoint regex to prevent unintended path matches.The
^anchor is functionally necessary, not optional. Nginx regex location blocks do not implicitly anchor at the start of the URI. Without^, the pattern would match any URI containing/sub/anywhere in the path (e.g.,/api/sub/fileor/dashboard/sub/item), routing those requests incorrectly to the nchan subscriber endpoint. The explicit^anchor correctly restricts matches to URIs that begin with/sub/.emhttp/plugins/dynamix/include/local_prepend.php (2)
33-38: LGTM: Improved readability.The multi-line formatting of the conditional improves readability without changing logic.
42-50: Excellent security enhancement with support for XHR/API token delivery.The implementation properly supports CSRF tokens from both POST fields and HTTP headers, which is essential for binary/chunked uploads. Key improvements verified:
- Uses
hash_equals()for timing-attack safe comparison- Maintains backward compatibility by preferring POST over header
- Properly cleans up both token sources after validation
- Both delivery methods are actively used in the codebase:
- XHR/header usage:
Browse.pagesetsX-CSRF-Tokenheader- POST usage: Multiple form implementations (DisplaySettings, UserEdit, UserAdd) submit tokens as hidden fields
emhttp/plugins/dynamix/styles/default-base.css (1)
94-118: LGTM - New CSS classes for UI enhancements.The
.small-caps-labeland.clipboard-tooltipclasses are well-structured and consistent with existing styling patterns in the file. The fixed positioning with centering transform for the tooltip is appropriate for clipboard feedback.emhttp/plugins/dynamix/include/Templates.php (2)
25-26: LGTM - Consistent template markup update.The change from
div.dfm_infotospan.dfm_textwith inline warning icons is applied consistently across all dialog templates. This addresses the Markdown parser regression mentioned in the PR objectives.
305-326: Permission select controls width update.The class change from
narrow dfmtodfmaddresses the PR objective to increase the width of permission selection controls. The change is applied consistently to Owner, Group, and Other selects.emhttp/plugins/dynamix/nchan/file_manager (4)
132-145: LGTM - Static state reset mechanism for transfer tracking.The reset parameter correctly clears all static variables (
$last_rsync_eta_seconds,$total_size,$total_calculations,$last_calc_percent) when starting a new transfer. This ensures clean state between operations.
167-199: Well-designed total size estimation with averaging.The multi-sample averaging approach (5 measurements at different progress percentages) effectively reduces the ~2% error per percent point caused by rsync's truncation behavior. The +0.5% adjustment is a reasonable heuristic to center the estimate.
344-348: JSON format migration for job parameters.Clean migration from INI to JSON format. The validation with
is_array($data)beforeextract()prevents issues with malformed JSON. This improves handling of special characters in filenames.
410-410: Correct placement of static state reset.The
parse_rsync_progress(null, null, true)call before starting copy operations ensures the total size estimation starts fresh for each transfer.emhttp/plugins/dynamix/include/PopularDestinations.php (1)
52-116: LGTM - Well-designed frequency-based scoring system.The scoring algorithm correctly:
- Finds the target path before decay
- Decays all non-target entries by 1
- Increments target by 10 (or creates it)
- Prunes non-positive scores
- Sorts and truncates
The
unset($dest)after the foreach reference loop is correctly placed to avoid reference issues.emhttp/plugins/dynamix/include/OpenTerminal.php (2)
54-90: Path-aware terminal launching implementation.The implementation correctly:
- Validates the path with
realpath()and falls back to/root- Properly escapes single quotes in the path
- Creates a startup script to change directory before launching bash
One consideration: The startup script at
/var/tmp/$name.run.shpersists after use. This is likely acceptable since the directory is tmpfs and the file is small.
77-78: The sed pattern is correct and should work on default Unraid systems.The default Unraid
/etc/profilecontains thecd $HOMEline that this pattern targets. The code itself documents this behavior (line 73 comment explicitly mentions it), and web search confirms the pattern exists in standard Unraid installations. No changes needed.Likely an incorrect or invalid review comment.
emhttp/plugins/dynamix/include/FileTree.php (1)
74-90: LGTM - FUSE conflict prevention logic.The filtering correctly prevents showing conflicting paths:
- In
/mnt/usercontext: only shows/mnt/userpaths or external mounts- In
/mnt/diskXcontext: excludes/mnt/userand/mnt/rootsharepathsThis prevents users from accidentally accessing the same data via both user shares and direct disk paths.
emhttp/plugins/dynamix/include/Browse.php (3)
85-86: LGTM - Broken symlink icon class.Appropriate visual indicator using
fa-chain-brokenwith red text for broken symlinks.
168-179: Robust directory listing with NULL separation.The new find command approach:
- Uses NULL-separated fields to handle filenames with newlines
- Separates working symlinks from broken symlinks with two find passes
- Includes symlink target information (
%l)The heredoc syntax with
BASHidentifier is clean.
188-225: LGTM - Device name extraction for symlinks.The logic correctly determines the device/location for both:
- Absolute symlinks: Uses the target path to find the actual storage location
- Relative symlinks/regular files: Uses the source path
This ensures the LOCATION column accurately reflects where the data physically resides.
emhttp/plugins/dynamix/include/Control.php (3)
46-46: LGTM - Flexible mode parameter handling.Using null-coalescing to check POST first, then GET, provides flexibility for different request types.
78-88: Raw binary upload with size validation.The new raw binary upload method reads directly from
php://inputwith a ~21MB limit. This is more efficient than base64 encoding (which has ~33% overhead).
222-226: LGTM - Popular destinations integration.Correctly updates popular destinations when copy/move operations (actions 3, 4, 8, 9) are queued or started, and the target is non-empty. Based on learnings, CSRF validation is handled globally.
emhttp/plugins/dynamix/Browse.page (9)
60-66: LGTM!The implementation correctly prevents the fileTree dropdown from closing by stopping mousedown event propagation. The namespaced event handler (
.dfmFileTree) allows for proper cleanup.
399-403: LGTM!The capture-phase event listeners are correctly implemented with proper cleanup on dialog close. This ensures the custom handlers run before the jQueryFileTree handlers and prevents memory leaks.
Also applies to: 525-533
536-644: LGTM with minor cleanup needed.The tree navigation functions are well-structured and handle asynchronous folder expansion appropriately with timeouts. The recursive approach in
openFolderRecursive()correctly handles the async nature of tree loading.Note: Console.log statements in
navigateFileTree()should be removed as flagged in the earlier comment.
698-698: LGTM!The increased dialog height (800px) for copy/move operations provides adequate space for the file tree navigation feature. This is consistent across all relevant actions (3, 4, 8, 9) and aligns with the PR's UI/UX improvements.
Also applies to: 708-708, 727-727, 735-735, 998-998, 1010-1010
785-787: LGTM!The dialog lifecycle management is correctly implemented:
closehandler removes the namespaced mousedown event to prevent memory leakspreventFileTreeClose()is called immediately after dialog creationsetupTargetNavigation()is conditionally invoked only for copy/move operations (actions 3, 4, 8, 9)Also applies to: 898-903, 1062-1064, 1178-1183
323-323: LGTM!The job queue iteration correctly extracts the queue index from element IDs. Per the PR objectives, this change corrects an off-by-one error in job queue numbering.
1189-1205: LGTM!The enhanced error handling provides better user feedback by categorizing upload failures (timeout, network, HTTP errors) and displaying appropriate localized messages. The addition of
currentXhr = nullensures proper cleanup.
1217-1289: LGTM!The rewrite to XMLHttpRequest provides significant improvements:
- Raw binary uploads eliminate Base64 overhead
- 20MB chunks improve upload performance
- Comprehensive error handling covers network failures, timeouts, and HTTP errors
- Proper abort handling allows user cancellation
- CSRF token protection is correctly implemented
The timeout calculation (1 minute per MB, minimum 10 minutes) is appropriate for various network conditions.
1291-1305: LGTM!The addition of
currentXhrenables proper upload cancellation. The cancel flow correctly:
- Sets the cancel flag
- Aborts the active XHR request
- Triggers the abort handler which performs cleanup
557dc5b to
2470a64
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (3)
emhttp/plugins/dynamix/include/FileTree.php (1)
71-71: Undefined variable$autocomplete.The variable
$autocompleteis used on line 71 but is not defined anywhere in this file. This will cause a PHP notice/warning and the condition will always evaluate to true (since undefined evaluates to falsy).🔎 Proposed fix
Add the variable extraction near line 61:
$match = $_POST['match']; $checkbox = $_POST['multiSelect'] == 'true' ? "<input type='checkbox'>" : ""; +$autocomplete = ($_POST['autocomplete'] ?? '') === 'true';emhttp/plugins/dynamix/Browse.page (2)
367-391: Remove debugging console.log statements before production.Multiple
console.logstatements remain throughoutsetupTargetNavigation()and related functions. These should be removed for production code as they create console noise and can impact performance.
1337-1394: Add user feedback or fallback for clipboard functionality on HTTP-only deployments.The Clipboard API requires HTTPS. While the code gracefully handles failures with
.catch(), users on HTTP-only deployments receive no indication that clipboard functionality is unavailable. Consider implementing a fallback usingdocument.execCommand('copy').The current implementation silently fails on HTTP. Consider:
- Detecting
window.isSecureContext- Using
execCommand('copy')as fallback- Showing a brief message when clipboard is unavailable
🧹 Nitpick comments (8)
emhttp/plugins/dynamix/nchan/file_manager (2)
167-199: Consider extracting hardcoded thresholds as constants.The total size calculation logic is well-designed and handles rsync's percent truncation correctly. However, the hardcoded values (3% minimum progress at line 178, 5 samples at line 195) could be extracted as named constants for better maintainability and self-documentation.
🔎 Proposed refactor to use named constants
+// Constants for total size calculation +const MIN_PERCENT_FOR_TOTAL_CALC = 3; +const TOTAL_SIZE_SAMPLE_COUNT = 5; + function parse_rsync_progress($status, $action_label, $reset = false) { static $last_rsync_eta_seconds = null; static $total_size = null; static $total_calculations = []; static $last_calc_percent = null; if ($reset) { $last_rsync_eta_seconds = null; $total_size = null; $total_calculations = []; $last_calc_percent = null; return []; } // ... existing code ... - if ($total_size === null || count($total_calculations) < 5) { + if ($total_size === null || count($total_calculations) < TOTAL_SIZE_SAMPLE_COUNT) { $percent_val = intval(str_replace('%', '', $percent)); $is_running_line = !isset($parts[4]); - if ($is_running_line && $percent_val >= 3 && $last_calc_percent !== $percent_val) { + if ($is_running_line && $percent_val >= MIN_PERCENT_FOR_TOTAL_CALC && $last_calc_percent !== $percent_val) { // ... calculation logic ... - if (count($total_calculations) >= 5) { + if (count($total_calculations) >= TOTAL_SIZE_SAMPLE_COUNT) { $total_size = array_sum($total_calculations) / count($total_calculations); } } }
82-89: Consider extracting unit conversion into helper functions.The unit conversion logic appears in three places (lines 82-89, 180-187, and 222-229). While the current implementation works correctly, extracting this into reusable helper functions would improve maintainability and reduce the risk of inconsistencies.
Example helpers:
function size_string_to_bytes($size_str) { $multipliers = ['K' => 1024, 'M' => 1024*1024, 'G' => 1024*1024*1024, 'T' => 1024*1024*1024*1024]; $bytes = floatval($size_str); foreach ($multipliers as $unit => $mult) { if (stripos($size_str, $unit) !== false) { return $bytes * $mult; } } return $bytes; } function bytes_to_display_size($bytes) { $units = ['TB' => 1024**4, 'GB' => 1024**3, 'MB' => 1024**2, 'KB' => 1024]; foreach ($units as $unit => $divisor) { if ($bytes >= $divisor) { return number_format($bytes / $divisor, 2) . $unit; } } return number_format($bytes, 2) . 'B'; }Also applies to: 180-187, 222-229
emhttp/plugins/dynamix/include/Browse.php (1)
191-206: Potential issue with relative symlink target containing/.The condition
$target[0] == '/'only checks if the symlink target starts with/. A relative symlink like../disk2/foowould fall through to the else branch and extract device name from the source path, which is correct. However, consider adding a comment clarifying this behavior for maintainability.🔎 Suggested documentation improvement
if ($target && $target[0] == '/') { // Absolute symlink: extract device from target path // Example: /mnt/disk2/foo/bar -> dev[2] = 'disk2' $dev = explode('/', $target, 5); $dev_name = $dev[2] ?? ''; } else { - // Regular file/folder or relative symlink: extract from source path + // Regular file/folder or relative symlink: extract from source path + // Note: Relative symlinks (e.g., ../disk2/foo) use source path for device, + // which is intentional as the symlink resides on the source device // Example: /mnt/disk1/sharename/foo -> dev[3] = 'sharename', dev[2] = 'disk1' $dev = explode('/', $name, 5); $dev_name = $dev[3] ?? $dev[2];emhttp/plugins/dynamix/include/Control.php (2)
77-88: Consider validating chunk data before writing.When reading raw binary from
php://input, the code checks size but doesn't validate that data was actually received. Iffile_get_contents('php://input')fails or returns false, it would still attempt to write.🔎 Proposed fix
} else { // New raw binary upload method (read from request body) $chunk = file_get_contents('php://input'); + if ($chunk === false) { + unlink($local); + die('error:read'); + } if (strlen($chunk) > 21000000) { // slightly more than 20MB to allow overhead unlink($local); die('error:chunksize:'.strlen($chunk)); } }
137-146: Missing error handling for malformed JSON in jobs listing.If a job file contains invalid JSON,
json_decodereturnsnulland the code silently skips it withif (!$data) continue;. This is acceptable for resilience, but consider logging these cases for debugging.emhttp/plugins/dynamix/include/OpenTerminal.php (1)
74-82: Consider cleaning up temporary files after shell exits.The script creates
/tmp/$name.profilebut relies on thermcommand within the script. If the shell is killed unexpectedly, this file may remain. Consider using a trap or ensuring cleanup in the parent script.🔎 Suggested improvement
$script_content = <<<BASH #!/bin/bash +trap 'rm -f /tmp/$name.profile' EXIT # Modify /etc/profile to replace 'cd \$HOME' with our target path sed 's#^cd \$HOME#cd '\''$escaped_path'\''#' /etc/profile > /tmp/$name.profile source /tmp/$name.profile source /root/.bash_profile 2>/dev/null -rm /tmp/$name.profile exec bash --norc -i BASH;emhttp/plugins/dynamix/Browse.page (2)
406-418: Potential memory leak with document-level event listener.The
treeClickHandleris attached todocumentin capture phase but cleanup indialogclosemay not fire if the dialog is destroyed without proper close. Consider also cleaning up in the dialog'scloseoption.🔎 Proposed improvement
The cleanup is already handled in
dialogcloseevent (lines 525-532), but consider adding defensive cleanup:// Cleanup on dialog close dfm.window.on('dialogclose', function() { document.removeEventListener('click', treeClickHandler, true); document.removeEventListener('click', popularClickHandler, true); if (inputElement) { inputElement.removeEventListener('mousedown', preventClose, true); inputElement.removeEventListener('focus', preventClose, true); inputElement.removeEventListener('click', preventClose, true); } }); + + // Also cleanup on destroy (in case close doesn't fire) + dfm.window.on('dialogdestroy', function() { + document.removeEventListener('click', treeClickHandler, true); + document.removeEventListener('click', popularClickHandler, true); + });
614-618: Timeout duration may be insufficient for deep paths.The timeout
parts.length * 300 + 500assumes each folder takes 300ms to expand. For slow network/disk or deeply nested paths, this may be insufficient.Consider using a completion callback or promise-based approach instead of fixed timeouts for more reliable navigation completion detection.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/nchan/file_manageremhttp/plugins/dynamix/sheets/BrowseButton.cssemhttp/plugins/dynamix/styles/default-base.cssemhttp/plugins/dynamix/styles/default-dynamix.cssetc/rc.d/rc.nginx
💤 Files with no reviewable changes (2)
- emhttp/plugins/dynamix/sheets/BrowseButton.css
- emhttp/plugins/dynamix/styles/default-dynamix.css
🚧 Files skipped from review as they are similar to previous changes (3)
- emhttp/plugins/dynamix/styles/default-base.css
- etc/rc.d/rc.nginx
- emhttp/plugins/dynamix/include/PopularDestinations.php
🧰 Additional context used
🧠 Learnings (7)
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/include/Templates.php
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Templates.php
🧬 Code graph analysis (3)
emhttp/plugins/dynamix/include/FileTree.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
getPopularDestinations(123-138)
emhttp/plugins/dynamix/include/Templates.php (1)
emhttp/plugins/dynamix/include/Helpers.php (1)
mk_option(182-184)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(52-116)
🔇 Additional comments (19)
emhttp/plugins/dynamix/nchan/file_manager (2)
211-235: LGTM! Clean progress display with proper localization.The progress text formatting properly localizes all user-facing strings and gracefully handles the edge case where total size hasn't been calculated yet. The unit conversion and display formatting are appropriate.
410-410: Excellent localization improvements!The explicit reset calls before copy/move operations ensure clean state management, and wrapping the error messages with
_()makes them properly localizable. This directly addresses one of the objectives from issue #2500.Also applies to: 420-420, 454-454, 521-521, 551-551
emhttp/plugins/dynamix/include/Browse.php (4)
85-86: LGTM!Good addition of the broken-symlink icon case with appropriate red styling to visually indicate broken links.
154-161: LGTM!The octal escape decoding correctly handles special characters (like newlines
\012) thatgetfattroutputs, ensuring proper filename matching with thefindresults.
168-179: LGTM!The two-phase
findapproach correctly separates working symlinks (! -xtype l) from broken symlinks (-xtype l), using NULL-separation to handle filenames with newlines. The 7-field format is well-documented.
242-247: LGTM!Broken symlink detection correctly maps to the special icon class and disables the
onclickhandler for broken items, preventing users from attempting to edit non-existent targets.emhttp/plugins/dynamix/include/Control.php (3)
164-177: LGTM!The start mode correctly reads the first JSON line, shifts it to active, and handles cleanup of the jobs file when empty.
185-199: Potential issue with array re-indexing after unset.After
unset($lines[$line_number]), the array has gaps. When writing back withimplode("\n", $lines), this works correctly, but if other code expects contiguous indices, it could cause issues. The current implementation is correct since you're just joining lines.
208-235: LGTM!The file mode correctly builds structured JSON data, triggers
updatePopularDestinations()for copy/move actions (3, 4, 8, 9), and handles both queue and immediate start flows consistently.emhttp/plugins/dynamix/include/Templates.php (2)
25-26: LGTM!The template changes consistently replace
<div class="dfm_info">with<span class="dfm_text">across all action dialogs, addressing the Markdown parser regression mentioned in issue #2500. The structure is now uniform.Also applies to: 36-37, 53-54, 76-78, 103-105, 118-119, 135-136, 158-160, 185-187, 200-201, 213-218, 240-242, 267-269, 290-292, 331-333
305-326: LGTM!Removing the
narrowclass from the permission select elements addresses the usability request in issue #2500 to increase the width of permission selection controls.emhttp/plugins/dynamix/include/OpenTerminal.php (1)
62-66: LGTM!Good defensive coding - falling back to
/rootwhen the requested path doesn't exist prevents errors while still providing terminal access.emhttp/plugins/dynamix/include/FileTree.php (3)
74-90: LGTM!The FUSE conflict prevention logic correctly filters popular destinations based on context:
- In
/mnt/usercontext: only shows/mnt/userpaths or external mounts- In
/mnt/diskXcontext: excludes/mnt/userand/mnt/rootsharepathsThis prevents users from accidentally creating cross-FUSE operations.
93-106: LGTM!Popular destinations are rendered with appropriate styling and use
data-pathinstead ofrelto prevent jQueryFileTree from handling these links directly, allowing custom click handling in Browse.page.
109-156: LGTM!The refactored directory reading logic correctly populates
$dirsand$filesarrays before rendering, supporting both normal and autocomplete modes with consistent behavior.emhttp/plugins/dynamix/Browse.page (4)
60-66: LGTM!The
preventFileTreeClose()function correctly uses a namespaced event handler (mousedown.dfmFileTree) that can be properly cleaned up on dialog close, preventing memory leaks.
1217-1230: LGTM on XHR upload implementation!The switch from jQuery AJAX to native XHR with:
- Raw binary uploads (no base64 overhead)
- Proper CSRF token header
- Configurable timeout based on chunk size
- Abort capability via
currentXhrThis is a significant improvement for upload reliability and performance.
1265-1276: Good abort handling with cleanup.The
onaborthandler correctly triggers server-side cleanup via the cancel parameter, ensuring partial uploads are removed. The.always()ensures UI cleanup regardless of POST result.
1351-1358: Good UX: Terminal button in path dialog.The "Terminal" button (using the cancel button slot) provides quick access to open a terminal at the displayed path, addressing the "Open Terminal here" feature request from issue #2500.
2470a64 to
2505068
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (7)
emhttp/plugins/dynamix/nchan/file_manager (1)
344-348: Consider adding error logging for JSON parse failures.While the code safely handles JSON decode failures via the
is_array()check, malformed JSON will silently fail. For a long-running daemon, this could make debugging difficult.🔎 Proposed enhancement
if (file_exists($active)) { $data = json_decode(file_get_contents($active), true); - if (is_array($data)) extract($data); + if (is_array($data)) { + extract($data); + } elseif ($data === null && json_last_error() !== JSON_ERROR_NONE) { + error_log("File Manager: Failed to parse JSON from $active: " . json_last_error_msg()); + } }emhttp/plugins/dynamix/Browse.page (4)
1282-1339: Add fallback for clipboard functionality on non-HTTPS deployments.The Clipboard API requires a secure context (HTTPS). While the
.catch()handles API failures silently, users on HTTP-only deployments receive no indication that clipboard copying failed. Consider adding a fallback usingdocument.execCommand('copy')or displaying a message.
354-534: Remove debugging console.log statements before merging.The
setupTargetNavigation()function contains numerousconsole.logstatements (lines 367, 372, 376-377, 379, 382, 387, 390, 465, 470, 484, 517, 519, etc.) that should be removed for production code.
556-579: Remove console.log statements from resetFileTree.Lines 557, 562, 571, 577 contain debugging statements that should be removed.
581-619: Remove console.log statements from navigateFileTree and openFolderRecursive.Lines 582, 585, 593, 596, 602, 605-609, 615 contain debugging statements.
emhttp/plugins/dynamix/include/OpenTerminal.php (1)
70-82: Escape sed metacharacters in the replacement string.The
str_replace("'", "'\\''", $real_path)correctly handles single quotes for shell interpretation, but sed replacement string special characters (&and\) are not escaped. In sed,&in the replacement string expands to the matched text, which will corrupt paths containing&. Consider escaping sed metacharacters:🔎 Proposed fix
- $escaped_path = str_replace("'", "'\\''", $real_path); + // Escape for sed replacement: & and \ are special + $sed_escaped = str_replace(['\\', '&'], ['\\\\', '\\&'], $real_path); + // Then escape for shell single quotes + $escaped_path = str_replace("'", "'\\''", $sed_escaped);emhttp/plugins/dynamix/include/FileTree.php (1)
71-71: Undefined variable$autocomplete.The variable
$autocompleteis used but not extracted from POST data. This will cause a PHP notice and the condition will always evaluate to false (treating undefined as falsy).🔎 Proposed fix
Add near line 61:
$match = $_POST['match']; $checkbox = $_POST['multiSelect'] == 'true' ? "<input type='checkbox'>" : ""; +$autocomplete = ($_POST['autocomplete'] ?? '') === 'true';
🧹 Nitpick comments (3)
emhttp/plugins/dynamix/include/OpenTerminal.php (1)
56-66: Consider validating the path is under allowed roots.The code validates that the path exists via
realpath(), but doesn't verify it's under an allowed root (e.g.,/mnt/or/boot/). A user could potentially open a terminal at any readable system directory. Consider adding root validation consistent with other file manager operations.🔎 Proposed enhancement
// Validate path $real_path = realpath($more); - if ($real_path === false) { + if ($real_path === false || !preg_match('#^/(mnt|boot)/#', $real_path)) { // Path doesn't exist - fall back to home directory $real_path = '/root'; }emhttp/plugins/dynamix/include/Control.php (1)
184-211: Verify action type comparison uses consistent types.At lines 200 and 208, actions are compared as strings (
'3', '4', '8', '9'), but$_POST['action']may arrive as a string from the form. This should work correctly, but consider usingin_array((int)$data['action'], [3, 4, 8, 9])for explicit type handling.🔎 Proposed fix for type consistency
- if (in_array($data['action'], ['3', '4', '8', '9']) && !empty($data['target'])) { + if (in_array((int)$data['action'], [3, 4, 8, 9]) && !empty($data['target'])) { updatePopularDestinations($data['target']); }emhttp/plugins/dynamix/include/PopularDestinations.php (1)
43-46: Consider adding error handling for file write operations.
file_put_contents()can fail (permissions, disk full, etc.) but the function doesn't check the return value or handle errors. While failures are unlikely on/boot/config/, adding basic error handling would improve robustness.🔎 Proposed enhancement
function savePopularDestinations($data) { $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); - file_put_contents(POPULAR_DESTINATIONS_FILE, $json); + $result = file_put_contents(POPULAR_DESTINATIONS_FILE, $json, LOCK_EX); + if ($result === false) { + error_log("PopularDestinations: Failed to write to " . POPULAR_DESTINATIONS_FILE); + } }Note:
LOCK_EXalso provides basic protection against concurrent writes.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/nchan/file_manageremhttp/plugins/dynamix/sheets/BrowseButton.cssemhttp/plugins/dynamix/styles/default-base.cssemhttp/plugins/dynamix/styles/default-dynamix.css
💤 Files with no reviewable changes (2)
- emhttp/plugins/dynamix/sheets/BrowseButton.css
- emhttp/plugins/dynamix/styles/default-dynamix.css
🚧 Files skipped from review as they are similar to previous changes (1)
- emhttp/plugins/dynamix/styles/default-base.css
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/include/Templates.php
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Templates.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-02-27T21:52:42.541Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/SyslogFilter.page:19-26
Timestamp: 2025-02-27T21:52:42.541Z
Learning: In the unraid/webgui repository, basic error handling is sufficient for file operations like checking file existence and using the @ operator to suppress errors, without additional error messages or notifications.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-02-27T21:53:37.589Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: etc/rc.d/rc.rsyslogd:48-50
Timestamp: 2025-02-27T21:53:37.589Z
Learning: For the unraid/webgui project, simple error handling is preferred over extensive error checking in shell scripts. The copy operation for configuration files like in rc.rsyslogd doesn't require additional error logging, permission checks, or return statements.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
🧬 Code graph analysis (4)
emhttp/plugins/dynamix/include/Templates.php (1)
emhttp/plugins/dynamix/include/Helpers.php (1)
mk_option(182-184)
emhttp/plugins/dynamix/include/Browse.php (4)
emhttp/plugins/dynamix/include/SmartInfo.php (1)
size(30-32)emhttp/plugins/dynamix/include/FileTree.php (1)
path(30-32)emhttp/plugins/dynamix/include/Helpers.php (1)
my_scale(19-39)emhttp/plugins/dynamix/include/Control.php (1)
my_age(26-36)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(52-116)
emhttp/plugins/dynamix/include/FileTree.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
getPopularDestinations(123-138)
🔇 Additional comments (22)
emhttp/plugins/dynamix/include/Templates.php (1)
25-26: LGTM - Consistent UI template updates.The changes uniformly switch from
<div class="dfm_info">to inline<span class="dfm_text">elements for warning notices, and simplify permission select controls by removing thenarrowclass. This aligns with the broader UI simplification effort in this PR.Also applies to: 36-37, 53-54, 76-78, 103-105, 117-119, 134-136, 158-160, 185-187, 199-201, 214-218, 240-242, 267-269, 290-292, 305-333
emhttp/plugins/dynamix/nchan/file_manager (3)
132-145: Good implementation of reset mechanism for static state.The
$resetparameter properly clears all static variables and returns an empty array, ensuring clean state between separate transfer operations. The calls at lines 410 and 454 correctly reset before starting new copy/move actions.
167-199: Total size estimation logic is well-designed.The multi-sample averaging approach (5 measurements at different percentages) accounts for rsync's percentage truncation and provides approximately 2% accuracy as documented. The +0.5% adjustment at line 190 is a reasonable heuristic for truncation compensation.
420-421: Good use of localization for error messages.The error messages are now properly wrapped with
_()for translation support, addressing one of the linked issue objectives.Also applies to: 521-522, 551-552
emhttp/plugins/dynamix/Browse.page (3)
60-66: Good approach for preventing fileTree closure within dialogs.The
preventFileTreeClose()function correctly uses event namespacing (.dfmFileTree) for proper cleanup and stops propagation to prevent the document-level handler from closing the tree.
785-787: Good cleanup of fileTree event handlers on dialog close.The dialog close handlers properly detach the
.dfmFileTreenamespaced events, preventing memory leaks and stale handlers.Also applies to: 1062-1064
698-699: Dialog height increase accommodates new navigation UI.The height increase from 630 to 800 for copy/move dialogs provides adequate space for the enhanced file tree navigation features.
Also applies to: 708-709, 727-728, 735-736, 998-999, 1010-1011
emhttp/plugins/dynamix/include/Control.php (3)
113-122: Good migration to JSON format for jobs queue.The JSON line-based approach is cleaner than INI parsing and handles complex data structures better. The empty/invalid line guards at lines 114 and 116 provide robust error handling.
140-154: Correct implementation of start operation with JSON.Reading the first line as JSON, writing to active, and shifting the array properly handles the queue. The cleanup when empty (line 150) is correct.
161-174: Index conversion handles 1-based to 0-based correctly.The conversion at line 163 (
$row - 1) properly maps user-facing job numbers to array indices.emhttp/plugins/dynamix/include/FileTree.php (3)
74-90: Good FUSE conflict prevention logic.The filtering correctly prevents showing
/mnt/userpaths when in disk context and vice versa, avoiding FUSE layer conflicts that could cause issues.
92-106: Popular destinations UI rendering is well-structured.The HTML structure with appropriate classes (
popular-header,popular-destination,popular-separator) and the use ofdata-pathinstead ofrelto prevent jQueryFileTree interference is a good approach.
109-130: Directory content reading refactored for clarity.Pre-populating
$dirsand$filesarrays before rendering improves code organization and makes the logic easier to follow.emhttp/plugins/dynamix/include/Browse.php (5)
85-87: Good addition of broken symlink icon support.The new
broken-symlinkcase withfa-chain-broken red-textprovides clear visual indication of broken symlinks.
154-161: Correct octal escape decoding for getfattr output.The
preg_replace_callbackproperly decodes octal escapes (like\012for newline) that getfattr outputs for special characters, ensuring accurate filename matching.
165-179: Robust NULL-separated find output for filenames with newlines.Using
\0as a field separator instead of newlines correctly handles filenames containing newline characters. The two-find approach (working symlinks vs broken symlinks) is elegant.
191-206: Correct device name derivation for symlinks.The logic properly distinguishes between absolute symlink targets (extracting device from target path) and regular files/relative symlinks (extracting from source path). This ensures the LOCATION column shows the actual storage location.
242-247: Good broken symlink detection and handling.Broken symlinks are correctly identified, assigned the
broken-symlinkextension for icon mapping, and have theironclickdisabled to prevent attempting to edit non-existent targets.emhttp/plugins/dynamix/include/PopularDestinations.php (4)
17-20: Well-defined configuration constants.The constants provide clear documentation of the scoring system parameters and make tuning straightforward.
25-38: Robust load function with proper fallbacks.The function handles missing files and malformed JSON gracefully by returning an empty destinations array.
52-116: Scoring algorithm is well-designed.The decay-on-update approach naturally ages out unused destinations while boosting frequently used ones. The implementation correctly:
- Skips invalid paths (empty,
/mnt,/boot)- Normalizes trailing slashes
- Finds target before decay to avoid double-processing
- Prunes zero/negative scores
- Maintains sorted order and respects
MAX_ENTRIES
123-138: Retrieval function is correct and defensive.Re-sorting before slicing ensures correctness even if the stored data is somehow out of order. Returning only the path strings (not full objects) is appropriate for the UI consumer.
2505068 to
bc0ea9a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (2)
emhttp/plugins/dynamix/include/FileTree.php (1)
71-71: Undefined variable$autocomplete.The variable
$autocompleteis used but never defined in this file. It should be extracted from POST data near line 61.🔎 Proposed fix
$match = $_POST['match']; $checkbox = $_POST['multiSelect'] == 'true' ? "<input type='checkbox'>" : ""; +$autocomplete = ($_POST['autocomplete'] ?? '') === 'true';emhttp/plugins/dynamix/Browse.page (1)
354-534: Remove debugging console.log statements before production.This function contains numerous
console.logstatements that should be removed for production code. These create unnecessary console noise and can impact performance.
🧹 Nitpick comments (6)
emhttp/plugins/dynamix/nchan/file_manager (3)
167-199: Extract duplicated byte-conversion logic.The multipliers array and byte conversion logic (lines 180-187) is duplicated from the
calculate_etafunction (lines 82-89). Extract this into a shared helper function to improve maintainability.🔎 Suggested refactor
Add a helper function before
calculate_eta:function convert_size_to_bytes($size_str) { $multipliers = ['K' => 1024, 'M' => 1024*1024, 'G' => 1024*1024*1024, 'T' => 1024*1024*1024*1024]; $bytes = floatval($size_str); foreach ($multipliers as $unit => $mult) { if (stripos($size_str, $unit) !== false) { $bytes *= $mult; break; } } return $bytes; }Then replace lines 180-187 with:
- // Convert transferred size to bytes - $multipliers = ['K' => 1024, 'M' => 1024*1024, 'G' => 1024*1024*1024, 'T' => 1024*1024*1024*1024]; - $transferred_bytes = floatval($transferred); - foreach ($multipliers as $unit => $mult) { - if (stripos($transferred, $unit) !== false) { - $transferred_bytes *= $mult; - break; - } - } + $transferred_bytes = convert_size_to_bytes($transferred);And similarly update
calculate_etato use the helper.
167-199: Document the total-size estimation constraints.The algorithm requires 5 samples at different percent values (≥3%) from running-transfer lines. For very small or fast transfers that complete before reaching 5 distinct percent values,
$total_sizeremains null and displays "N/A". Consider adding a comment explaining these constraints and the 0.5% truncation-adjustment heuristic.
410-410: Consider a dedicated reset method for clarity.The calls
parse_rsync_progress(null, null, true)correctly reset state but are not self-documenting. While functional, a dedicated static method or a clearer API (e.g.,reset_rsync_progress()) would improve code readability.💡 Alternative approach
Extract the reset logic:
function reset_rsync_progress() { parse_rsync_progress(null, null, true); }Then use:
- parse_rsync_progress(null, null, true); // Reset static variables + reset_rsync_progress(); // Reset static variables before new transferAlso applies to: 454-454
emhttp/plugins/dynamix/include/FileTree.php (1)
80-88:array_filterdoes not reindex arrays by default.While this doesn't cause an issue in the current
foreachusage, it may cause unexpected behavior if the array is later used with index-based access. Consider usingarray_values()to reindex after filtering.🔎 Proposed fix
if ($isUserContext) { // In /mnt/user context: only show /mnt/user paths OR non-/mnt paths (external mounts) - $popularPaths = array_filter($popularPaths, function($path) { + $popularPaths = array_values(array_filter($popularPaths, function($path) { return (strpos($path, '/mnt/user') === 0 || strpos($path, '/mnt/rootshare') === 0 || strpos($path, '/mnt/') !== 0); - }); + })); } else if (strpos($root, '/mnt/') === 0) { // In /mnt/diskX or /mnt/cache context: exclude /mnt/user and /mnt/rootshare paths - $popularPaths = array_filter($popularPaths, function($path) { + $popularPaths = array_values(array_filter($popularPaths, function($path) { return (strpos($path, '/mnt/user') !== 0 && strpos($path, '/mnt/rootshare') !== 0); - }); + })); }emhttp/plugins/dynamix/include/PopularDestinations.php (1)
52-59: Path validation could be bypassed with path traversal.While
/mntand/bootare explicitly blocked, paths containing..or other traversal sequences are not validated. Consider adding additional validation to ensure paths are within expected directories.🔎 Proposed fix
function updatePopularDestinations($targetPath) { // Skip empty paths or paths that are just /mnt or /boot if (empty($targetPath) || $targetPath == '/mnt' || $targetPath == '/boot') { return; } + // Validate path is within allowed directories + $realPath = realpath($targetPath); + if ($realPath === false || (strpos($realPath, '/mnt/') !== 0 && strpos($realPath, '/boot/') !== 0)) { + return; + } + // Normalize path (remove trailing slash) $targetPath = rtrim($targetPath, '/');emhttp/plugins/dynamix/Browse.page (1)
613-618: Timeout calculation for flag reset may be too short for deep paths.The formula
parts.length * 300 + 500gives 800ms for a path 1 level deep, but network latency or slow filesystem responses could cause the flag to reset before navigation completes, leading to input value restoration issues.Consider using a completion callback from
openFolderRecursiveinstead of a fixed timeout, or increase the base timeout.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/Templates.phpemhttp/plugins/dynamix/nchan/file_manageremhttp/plugins/dynamix/sheets/BrowseButton.cssemhttp/plugins/dynamix/styles/default-base.cssemhttp/plugins/dynamix/styles/default-dynamix.css
💤 Files with no reviewable changes (2)
- emhttp/plugins/dynamix/styles/default-dynamix.css
- emhttp/plugins/dynamix/sheets/BrowseButton.css
🚧 Files skipped from review as they are similar to previous changes (2)
- emhttp/plugins/dynamix/include/OpenTerminal.php
- emhttp/plugins/dynamix/include/Templates.php
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-02-27T21:52:42.541Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/SyslogFilter.page:19-26
Timestamp: 2025-02-27T21:52:42.541Z
Learning: In the unraid/webgui repository, basic error handling is sufficient for file operations like checking file existence and using the @ operator to suppress errors, without additional error messages or notifications.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manageremhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-02-27T21:53:37.589Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: etc/rc.d/rc.rsyslogd:48-50
Timestamp: 2025-02-27T21:53:37.589Z
Learning: For the unraid/webgui project, simple error handling is preferred over extensive error checking in shell scripts. The copy operation for configuration files like in rc.rsyslogd doesn't require additional error logging, permission checks, or return statements.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/Browse.php
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/styles/default-base.css
📚 Learning: 2025-12-30T20:27:59.455Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:27:59.455Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🧬 Code graph analysis (2)
emhttp/plugins/dynamix/include/FileTree.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
getPopularDestinations(123-138)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(52-116)
🔇 Additional comments (20)
emhttp/plugins/dynamix/nchan/file_manager (2)
211-235: LGTM!The progress display formatting correctly handles both calculated and unavailable total-size cases, with proper localization and unit conversion.
420-420: LGTM!Error messages are now properly wrapped for localization, making them translation-ready and consistent with the rest of the file's localized strings.
Also applies to: 521-521, 551-551
emhttp/plugins/dynamix/styles/default-base.css (1)
94-118: Unused CSS class and code duplication detected.The
.clipboard-tooltipclass (lines 101-118) is defined in the stylesheet but does not appear to be used anywhere in the codebase. If this is incomplete feature work, consider either implementing its usage or removing the unused CSS. The z-index and positioning concerns in the definition are moot if the class is not applied.Additionally,
.small-caps-label(lines 94-100) duplicates 5 properties from the existinga.info spanstyles (lines 73-89):white-space,font-variant,line-height,color. Consider extracting these shared properties into a reusable base class to reduce duplication and maintenance burden.⛔ Skipped due to learnings
Learnt from: zackspear Repo: unraid/webgui PR: 2258 File: emhttp/plugins/dynamix/DashStats.page:0-0 Timestamp: 2025-06-21T00:10:40.789Z Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.emhttp/plugins/dynamix/include/FileTree.php (1)
93-106: Popular destinations rendering looks good.The implementation correctly:
- Adds a header with proper styling
- Truncates long names for display
- Uses
data-pathto avoid jQueryFileTree interference- Includes a visual separator
emhttp/plugins/dynamix/include/Browse.php (4)
85-86: Good addition of broken symlink visual indicator.The
fa-chain-broken red-texticon clearly indicates broken symlinks to users.
168-173: The two-find approach for symlink handling is well-designed.Using
-xtype lto detect broken symlinks separately from regular entries ensures accurate type detection. The NULL-separator approach correctly handles filenames with newlines.
182-186: Potential issue with incomplete entries at the end of output.If the find command output is truncated or malformed, the loop condition
$i + 7 <= count($fields_array)may miss this. Additionally, the last element afterexplode("\0", ...)will be an empty string due to the trailing\0, which is handled correctly by the loop condition.
242-247: Broken symlink handling correctly disables file editing.The conditional
onclickattribute prevents users from attempting to edit broken symlinks, which would fail. Thenl2br()usage preserves newlines in filenames for display.emhttp/plugins/dynamix/include/PopularDestinations.php (2)
77-85: Reference variable in foreach requires explicit unset.The
&$destreference is correctly unset on line 85. This prevents the common PHP pitfall where the reference remains bound after the loop.
123-138:getPopularDestinationsimplementation is clean and correct.The function correctly loads data, sorts by score, and returns only the paths. The defensive re-sort on line 128 is a good safeguard.
emhttp/plugins/dynamix/include/Control.php (4)
164-177: Start mode correctly handles the new JSON line-based queue.The logic properly:
- Reads the first line as the active job
- Removes it from the queue
- Cleans up empty queue files
- Returns appropriate state codes (0/1/2)
184-198: Off-by-one fix in undo mode is correct.The conversion from 1-based job numbers (user-facing) to 0-based array indices (
$row - 1) properly addresses the off-by-one issue mentioned in the PR objectives.
222-234: Popular destinations integration for copy/move operations.The code correctly updates popular destinations only for relevant actions (3=copy folder, 4=move folder, 8=copy file, 9=move file) and checks for non-empty targets. This is called in both direct start and queue paths.
78-88: Raw binary upload with size validation is a good security measure.The 21MB limit check prevents memory exhaustion from oversized chunks. The dual-method approach (legacy base64 vs new raw binary) maintains backward compatibility.
emhttp/plugins/dynamix/Browse.page (6)
60-66:preventFileTreeClosecorrectly prevents dialog dismissal.Using namespaced event binding (
mousedown.dfmFileTree) allows proper cleanup on dialog close (lines 786, 1063).
406-418: Document-level event listener attached in capture phase.The
treeClickHandleris attached todocumentin capture phase (line 418) and properly cleaned up on dialog close (line 526). This pattern is correct for intercepting events before they bubble.
1219-1230: Upload chunk size increased with appropriate timeout scaling.The 20MB raw binary chunks (vs previous base64-encoded) reduce overhead. The timeout calculation
Math.max(600000, slice / 1024 * 60)provides ~1 minute per MB with a 10-minute minimum, which is reasonable for large files on slow connections.
1265-1276: XHR abort handler properly triggers server-side cleanup.When the user cancels, the handler sends a cancel request to delete the partial upload, then cleans up the UI. Using
.always()ensures UI cleanup happens regardless of the cleanup POST's success.
1337-1394: Clipboard functionality intentionally silent-fails on HTTP.Based on learnings, this is the intended behavior - the path is pre-selected for manual copying on HTTP connections, and showing repetitive errors would degrade user experience.
698-735: Dialog height increases accommodate new navigation UI.The height changes from 630 to 800 for copy/move dialogs provide space for the enhanced file tree navigation features.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
emhttp/plugins/dynamix/include/Control.php (1)
164-177: Validate JSON before writing to active file.The first line from the jobs queue is written to the active file without verifying it's valid JSON. If a corrupted or legacy-format entry is first in queue, the backend will receive invalid data. Consider validating with
json_decode()before writing, consistent with the 'jobs' case handling.Suggested validation
$lines = file($jobs, FILE_IGNORE_NEW_LINES); if (!empty($lines)) { - file_put_contents($active, $lines[0]); + $firstJob = $lines[0]; + // Validate JSON before writing to active + if (json_decode($firstJob, true) !== null || $firstJob === 'null') { + file_put_contents($active, $firstJob); + } else { + // Skip invalid entry, try next line or handle error + // For now, write anyway for backward compatibility + file_put_contents($active, $firstJob); + }
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/include/Control.php (1)
54-61: Variable$fileis shadowed, reducing clarity.The validated
$filefrom line 48 is overwritten on line 56 with the contents read from$local. While functionally correct (the condition on line 57 handlesfalse), using a distinct variable name like$targetFilewould improve readability.Suggested improvement
if ($cancel==1) { if (file_exists($local)) { - $file = file_get_contents($local); - if ($file !== false) delete_file($file); + $targetFile = file_get_contents($local); + if ($targetFile !== false) delete_file($targetFile); } delete_file($local); die('stop'); }
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
emhttp/plugins/dynamix/include/Control.php
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(52-116)
🔇 Additional comments (5)
emhttp/plugins/dynamix/include/Control.php (5)
46-51: Verify intentional GET parameter support for upload operations.Accepting
mode,file,start, andcancelfrom GET parameters exposes these operations to URL-based triggering. While CSRF protection is centralized, GET requests are logged in server access logs and can be cached/bookmarked. Ensure this is intentional for the upload use case.
137-146: LGTM on graceful JSON parsing.The jobs display correctly handles empty lines and invalid JSON entries by skipping them, ensuring robustness when processing the queue file.
184-198: LGTM on undo logic.Processing rows in reverse order correctly preserves index validity during removal. The conversion from 1-based job numbers to 0-based array indices is handled properly.
208-231: LGTM on JSON-based state storage and popular destinations integration.The structured array approach with JSON encoding improves maintainability over the previous INI-like format. The popular destinations update is correctly triggered only for copy/move operations (actions 3, 4, 8, 9) when a target is provided.
201-204: LGTM.Reading the active file as raw content is appropriate since consumers will parse the JSON response.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (2)
emhttp/plugins/dynamix/include/Control.php (1)
140-153: Validate JSON before promoting job to active file.Line 143 writes
$lines[0]directly to the active file without validating it's well-formed JSON. If a legacy INI-format entry or corrupted JSON is first in the queue, the backend will receive invalid data and the job will fail. The 'jobs' case gracefully skips non-JSON lines (line 116), but 'start' does not apply the same safeguard.🔎 Proposed fix
// read first JSON line from jobs file and write to active $lines = file($jobs, FILE_IGNORE_NEW_LINES); if (!empty($lines)) { - file_put_contents($active, $lines[0]); + // Validate JSON before writing to active file + $data = json_decode($lines[0], true); + if (!$data) { + // Skip invalid JSON and try next line + array_shift($lines); + if (count($lines) > 0) { + file_put_contents($jobs, implode("\n", $lines)."\n"); + } else { + delete_file($jobs); + } + die('0'); + } + file_put_contents($active, $lines[0]); // remove first line from jobs fileemhttp/plugins/dynamix/Browse.page (1)
354-534: Remove debugging console.log statements before production.This function contains numerous console.log statements (lines 367, 372, 376-377, 379, 382, 387, 390, 465, 470, 484, 517, 519, 557, 562, 571, 577, 582, 585, 593, 605-609, 615) that should be removed for production code. These create unnecessary console noise and can impact performance.
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/Browse.page (1)
354-534: Consider refactoring for improved maintainability.This 180-line function handles multiple concerns: event prevention, popular destination clicks, tree navigation, input handling, and cleanup. Breaking it into smaller, focused functions would improve readability and testability.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.php
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-12-30T20:27:59.455Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:27:59.455Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(52-116)
🔇 Additional comments (11)
emhttp/plugins/dynamix/include/Control.php (3)
16-16: LGTM: Popular destinations dependency added.The include is correctly positioned in the bootstrap sequence.
113-122: LGTM: Graceful JSON parsing handles legacy entries.The
if (!$data) continue;on line 116 ensures non-JSON or malformed entries are silently skipped, preventing queue display breakage from legacy INI-format jobs.
184-206: Action codes verified as copy/move operations.The condition on line 204 correctly restricts
updatePopularDestinationsto copy and move operations. Action codes 3, 4, 8, and 9 are explicitly documented in Browse.page (line 900) as:
- 3 = copy folder
- 4 = move folder
- 8 = copy file
- 9 = move file
The integration is correct.
emhttp/plugins/dynamix/Browse.page (8)
60-66: LGTM!The function correctly uses namespaced events and event propagation control to prevent the fileTree dropdown from closing when clicking inside dialogs.
536-554: LGTM!The function correctly handles folder collapsing with appropriate early returns and DOM manipulation.
621-644: LGTM!The recursive folder expansion logic correctly handles asynchronous tree expansion with appropriate delays (300ms per level, matching the timing in
navigateFileTree).
698-698: Height increase accommodates new navigation UI.The dialog height increase from 630 to 800 for copy/move operations appropriately accommodates the new file tree navigation features. The change is consistently applied across both single-item (doAction) and batch (doActions) operations.
Also applies to: 708-708, 727-727, 735-735, 998-998, 1010-1010
785-787: LGTM!The cleanup handlers properly remove namespaced event listeners when dialogs close, preventing memory leaks.
Also applies to: 1062-1064
898-903: LGTM!The integration calls correctly wire up the navigation features after dialog creation, with appropriate conditional checks for copy/move operations that require target selection.
Also applies to: 1178-1183
323-323: LGTM!The fix to job queue numbering correctly extracts the queue index, addressing the off-by-one issue mentioned in the PR objectives.
1282-1339: LGTM!The xlink() rewrite implements the new features well:
- Textarea approach provides better mobile support for path selection
- Clipboard functionality gracefully degrades on HTTP (silent fail with pre-selected text for manual copy)
- Terminal integration adds the requested "Open Terminal here" feature
- Success feedback tooltip enhances UX
The
openTerminal()function is properly defined inemhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.phpand accepts the expected three-parameter signature (tag, name, more), matching the call in xlink().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (3)
emhttp/plugins/dynamix/nchan/file_manager (1)
355-365: JSON parsing with error logging addresses the previous review feedback.The implementation now logs a warning when JSON parsing fails for non-empty content, which aids debugging without breaking functionality.
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
43-49: File locking and error handling properly implemented.The
LOCK_EXflag prevents concurrent write corruption, and write failures are now logged. This addresses the previous review feedback.emhttp/plugins/dynamix/include/FileTree.php (1)
62-62: The$autocompletevariable is now properly defined.This addresses the previous review comment about the undefined variable.
🧹 Nitpick comments (3)
emhttp/plugins/dynamix/include/FileTree.php (1)
94-94: Consider using translation wrapper for "Popular" label.The "Popular" header text is hardcoded. For consistency with other localized strings in the codebase, consider wrapping it with a translation function.
🔎 Proposed fix
- echo "<li class='popular-header small-caps-label' style='list-style:none;padding:5px 0 5px 20px;'>Popular</li>"; + echo "<li class='popular-header small-caps-label' style='list-style:none;padding:5px 0 5px 20px;'>" . _('Popular') . "</li>";Note: This requires including the Translations.php file in FileTree.php if not already available.
emhttp/plugins/dynamix/Browse.page (2)
585-588: Timing calculation assumes 300ms per folder expansion.The timeout
parts.length * 300 + 500should align with the 300ms delay used inopenFolderRecursive(line 612). Consider extracting this to a named constant for maintainability.🔎 Suggested improvement
// At the top of the script section var FOLDER_EXPAND_DELAY = 300; // In openFolderRecursive (line 610-612) setTimeout(function() { openFolderRecursive($tree, pickroot, parts, index + 1); }, FOLDER_EXPAND_DELAY); // In navigateFileTree (line 585-588) setTimeout(function() { $target.data('isProgrammaticNavigation', false); $target.data('savedInputValue', ''); }, parts.length * FOLDER_EXPAND_DELAY + 500);
323-323: Minor: Variable shadowing withrowarray.The
rowvariable is used both for the array being built and later in the loop iteration. While this works, using a more descriptive name likeselectedRowswould improve readability.🔎 Suggested improvement
- let row = []; - dfm.window.find('i[id^="queue_"]').each(function(){if ($(this).hasClass('fa-check-square-o')) row.push($(this).prop('id').split('_')[1]);}); - $.post('/webGui/include/Control.php',{mode:'undo',row:row.join(',')},function(queue){ + let selectedRows = []; + dfm.window.find('i[id^="queue_"]').each(function(){if ($(this).hasClass('fa-check-square-o')) selectedRows.push($(this).prop('id').split('_')[1]);}); + $.post('/webGui/include/Control.php',{mode:'undo',row:selectedRows.join(',')},function(queue){
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.phpemhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/nchan/file_manager
🧰 Additional context used
🧠 Learnings (13)
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/OpenTerminal.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-09-03T08:33:04.940Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2352
File: emhttp/plugins/dynamix.plugin.manager/include/PluginHelpers.php:0-0
Timestamp: 2025-09-03T08:33:04.940Z
Learning: In the unraid/webgui codebase, Squidly271 prefers file locking to be handled centrally within the file_put_contents_atomic function rather than in individual functions that use it. This maintains cleaner architecture by centralizing the locking mechanism.
Applied to files:
emhttp/plugins/dynamix/include/PopularDestinations.php
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-02-27T21:52:42.541Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/SyslogFilter.page:19-26
Timestamp: 2025-02-27T21:52:42.541Z
Learning: In the unraid/webgui repository, basic error handling is sufficient for file operations like checking file existence and using the @ operator to suppress errors, without additional error messages or notifications.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manageremhttp/plugins/dynamix/include/FileTree.php
📚 Learning: 2025-02-27T21:53:37.589Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: etc/rc.d/rc.rsyslogd:48-50
Timestamp: 2025-02-27T21:53:37.589Z
Learning: For the unraid/webgui project, simple error handling is preferred over extensive error checking in shell scripts. The copy operation for configuration files like in rc.rsyslogd doesn't require additional error logging, permission checks, or return statements.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-12-30T20:27:59.455Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:27:59.455Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🧬 Code graph analysis (2)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(55-119)
emhttp/plugins/dynamix/include/FileTree.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
getPopularDestinations(126-141)
🔇 Additional comments (17)
emhttp/plugins/dynamix/nchan/file_manager (3)
132-156: Docblock and reset logic look good.The docblock properly documents the function's purpose, parameters, and the static-state reset behavior. The reset mechanism correctly clears all static variables when
$resetistrue.
178-210: Multi-sample averaging for total size estimation is well implemented.The approach of collecting up to 5 measurements at different progress percentages and averaging them compensates for rsync's truncation behavior. The logic correctly:
- Only samples from "running transfer" lines (no
xfr#info)- Waits for at least 3% progress before sampling
- Tracks
$last_calc_percentto avoid duplicate samples at the same percentage- Adds 0.5% adjustment to compensate for truncation
427-427: Reset calls before copy/move operations are correctly placed.Calling
parse_rsync_progress(null, null, true)before starting copy (line 427) and move (line 471) operations ensures clean state and prevents cross-operation contamination.Also applies to: 471-471
emhttp/plugins/dynamix/include/PopularDestinations.php (2)
98-114: Re-indexing after array_filter is correctly handled.Line 114 (
$destinations = array_values($destinations)) properly re-indexes the array afterarray_filterremoves entries with score ≤ 0, ensuring consistent 0-based numeric keys in the saved JSON.
55-96: Add defensive normalization on load for robustness.While the current code prevents trailing-slash paths under normal operation (by normalizing before storage), the
loadPopularDestinations()function should normalize loaded paths as well. This ensures consistency if the JSON file is modified externally or populated from legacy data sources, preventing duplicate entries from paths like/mnt/disk1and/mnt/disk1/.emhttp/plugins/dynamix/include/OpenTerminal.php (3)
76-84: Startup script generation looks correct.The heredoc properly sources the modified profile, handles
.bash_profileloading, cleans up temporary files, and launches an interactive bash session. The use ofexec bash --norc -iprevents double-sourcing of rc files.
62-66: Path validation with realpath fallback is appropriate.Using
realpath()validates the path exists and resolves symlinks. Falling back to/rootfor invalid paths is a safe default.
70-72: The escaping implementation at lines 70-72 is correct and does not suffer from the re-escaping concern raised. PHP'sstr_replace()with an array argument processes all replacements simultaneously rather than sequentially, preventing cascading escapes. Testing confirms that when both&and\are present in a path (e.g.,/mnt/test&\mixed), they are each escaped exactly once (\&and\\respectively) without double-escaping. The code properly escapes sed metacharacters for safe use in the replacement string.Likely an incorrect or invalid review comment.
emhttp/plugins/dynamix/include/Control.php (2)
113-122: JSON parsing for jobs listing handles edge cases correctly.The code properly skips empty rows and invalid JSON entries with
continue, preventing display issues from malformed data.
216-220: Popular destinations update integration is correct.Updating popular destinations for copy/move actions (3, 4, 8, 9) with non-empty targets is the appropriate behavior for tracking frequently used destinations.
emhttp/plugins/dynamix/include/FileTree.php (2)
76-91: FUSE conflict filtering logic is comprehensive.The filtering correctly handles:
/mnt/userand/mnt/rootsharecontexts: only shows paths from the same context or external mounts/mnt/diskXor/mnt/cachecontexts: excludes user share paths- Non-
/mnt/roots: no filtering neededThis prevents confusing users by showing inaccessible paths.
93-107: Popular destinations UI rendering is well-structured.Using
data-pathinstead ofrelattribute correctly prevents jQueryFileTree from intercepting clicks, allowing custom handling in JavaScript. The separator line provides clear visual distinction.emhttp/plugins/dynamix/Browse.page (5)
60-66: Event propagation prevention for fileTree is correctly implemented.Using
stopPropagation()on mousedown events within the dialog prevents the document-level handler in jQueryFileTree from closing the dropdown when interacting with the dialog.
376-378: Retain console.error for actual error conditions.The
console.erroron line 377 is appropriate for logging actual errors (tree show failures), unlike debugconsole.logstatements which should be removed. This is acceptable for production.
508-517: Dialog close cleanup properly removes event listeners.The cleanup function correctly removes all three capture-phase event listeners (treeClickHandler, popularClickHandler, preventClose handlers), preventing memory leaks and stale handlers.
755-757: Dialog close handlers properly detach fileTree event handlers.Both
doActionanddoActionsdialogs now clean up the.dfmFileTreenamespace handlers on close, ensuring proper cleanup.Also applies to: 1032-1034
1252-1309: Clipboard functionality correctly handles HTTP limitations.Based on the learnings, the silent failure on HTTP is intentional. The path is pre-selected for manual copying, and the Terminal button provides an alternative workflow. This is a pragmatic UX decision.
- Extract rsync progress thresholds as constants (RSYNC_MIN_PROGRESS_PERCENT, RSYNC_TOTAL_SIZE_SAMPLES) - Add helper functions for unit conversion (size_to_bytes, bytes_to_size) - Use explicit int casting for action type comparisons in Control.php - Reduces code duplication and improves maintainability Addresses PR feedback for code quality improvements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/nchan/file_manager (1)
84-120: Well-implemented size conversion helpers.The
size_to_bytesandbytes_to_sizefunctions are well-documented and correctly handle unit conversions. The case-insensitive unit detection withstriposis appropriate.Optional: Consider locale-independent formatting
The
number_format()function inbytes_to_sizeis locale-dependent for decimal separators (e.g., "1,50GB" in some locales vs "1.50GB"). If this output is ever parsed programmatically, consider usingsprintf('%.2f', $display)instead. For display-only purposes, the current implementation is fine.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/nchan/file_manager
🧰 Additional context used
🧠 Learnings (14)
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-10-03T02:57:29.994Z
Learnt from: ljm42
Repo: unraid/webgui PR: 2414
File: etc/rc.d/rc.nginx:374-376
Timestamp: 2025-10-03T02:57:29.994Z
Learning: Repo unraid/webgui: In etc/rc.d/rc.nginx, maintainers prefer not to add explicit mv-failure checks or EXIT trap clearing around atomic writes in build_servers(), build_locations(), and build_ini(); treat mv failures (e.g., disk full/permissions) as non-recoverable and keep the implementation simple.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/nchan/file_manager
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-30T20:27:59.455Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:27:59.455Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-02-27T21:52:42.541Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/SyslogFilter.page:19-26
Timestamp: 2025-02-27T21:52:42.541Z
Learning: In the unraid/webgui repository, basic error handling is sufficient for file operations like checking file existence and using the @ operator to suppress errors, without additional error messages or notifications.
Applied to files:
emhttp/plugins/dynamix/nchan/file_manager
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(55-119)
🔇 Additional comments (22)
emhttp/plugins/dynamix/include/Control.php (4)
16-16: LGTM!The PopularDestinations module inclusion is correctly placed and properly utilized later in the file (line 223).
140-172: LGTM! Past review concern addressed.The validation loop (lines 144-152) correctly skips invalid JSON entries until a valid one is found, and properly handles the case when no valid entries remain (lines 154-158). This successfully addresses the past review comment about the problematic
returnstatement that would have exited the script entirely.The implementation now correctly processes remaining entries without exiting the included script.
201-224: LGTM! Well-structured integration.The structured data array (lines 201-210) with explicit type casting is cleaner than string assembly. The popular destinations integration (lines 220-224) is correctly implemented:
- Only tracks copy/move operations (actions 3, 4, 8, 9)
- Validates target is not empty before updating
- Executes for both queued and immediate operations
- Aligns with the PopularDestinations API (which filters dangerous paths like
/mntand/boot)
113-122: Confirm the carriage return delimiter on line 118 is intentional.The code correctly handles JSON parsing and invalid entries with appropriate null checks and continue statements. However, line 118 uses
"\r"(carriage return) as the delimiter for splitting multiple source paths, which is an unusual choice. Standard practice would be"\n"(line feed) or"\r\n"(CRLF).This appears to be working code, but please verify:
- The
sourcefield from the client is actually separated by carriage returns- If this delimiter choice was deliberate or inherited from legacy code
If
"\r"is incorrect, it should be changed to match how the client constructs the source field.emhttp/plugins/dynamix/nchan/file_manager (8)
24-27: LGTM!The named constants for rsync progress calculation improve code readability and maintainability. The threshold values (3% minimum progress, 5 samples for averaging) are reasonable for balancing accuracy with responsiveness.
122-158: LGTM! ETA calculation with hysteresis is well-implemented.The refactored
calculate_etafunction correctly uses the new byte conversion helpers and implements reasonable hysteresis (70/30 blend) to smooth out ETA fluctuations. Edge cases for 0% progress and low/zero speed are properly handled.
160-184: Excellent documentation and reset mechanism.The comprehensive PHPDoc clearly explains the static state management and reset behavior. The
$resetparameter implementation properly clears all static variables to prevent state leakage between operations. This addresses the previous review comment requesting documentation.
206-231: LGTM! Total size estimation with multi-sample averaging is sound.The total size calculation logic is well-designed. The 0.5% compensation for rsync's percent truncation and the multi-sample averaging strategy at different progress points should achieve the claimed ~2% accuracy. The conditional logic correctly prevents recalculation at the same percent and stops array growth after reaching the sample limit.
243-256: LGTM! Progress text properly internationalized.The progress text construction correctly wraps all user-facing strings with
_()for translation. The "~" prefix on the total size appropriately indicates that it's an approximation, and the fallback to "N/A" gracefully handles cases where the total hasn't been calculated yet.
365-375: LGTM! JSON parameter loading with proper error handling.The switch from INI to JSON-based parameter loading is well-implemented. The error logging for parse failures (previously requested) has been properly addressed, using
loggerwith safely escaped content limited to 100 characters to prevent log spam.
437-437: LGTM! Static state reset properly called at operation boundaries.The
parse_rsync_progress(null, null, true)calls correctly reset static variables before starting new copy and move operations, preventing state leakage between transfers as documented in the function's PHPDoc.Also applies to: 481-481
447-447: LGTM! Error messages properly internationalized.The error messages are correctly wrapped with
_()for translation support, addressing the requirement from issue #2500 to enable localization of hardcoded English messages.Also applies to: 548-548, 578-578
emhttp/plugins/dynamix/Browse.page (10)
60-66: LGTM! Clean event handler management.The function correctly prevents fileTree dropdown closure by stopping mousedown propagation. The use of namespaced events (
.dfmFileTree) enables targeted cleanup later.
354-356: Well-named constants improve maintainability.Extracting timing values into clearly named constants (FOLDER_EXPAND_DELAY, NAVIGATION_BUFFER) makes the navigation timing logic self-documenting and easier to tune.
358-522: Complex orchestration handled well.This 160+ line function coordinates multiple concerns (event prevention, popular destinations, navigation, input handling), but the implementation is sound:
- Capture-phase event handling correctly prevents tree closure
- Flag management (isNavigatingFromPopular, isProgrammaticNavigation) prevents recursive triggers
- Comprehensive cleanup on dialog close prevents memory leaks
- Debouncing (200ms timeout) prevents excessive navigation calls
The mixing of native
addEventListener(required for capture phase) with jQuery handlers is necessary and properly managed.
524-618: Well-designed navigation helpers.The four helper functions form a cohesive API:
closeFolderPath()cleanly collapses folders by toggling classes and removing child elementsresetFileTree()properly sequences hide → empty → reload with setTimeoutnavigateFileTree()usesjQuery.data()to pass state without polluting global scopeopenFolderRecursive()handles all cases (already expanded, collapsed, base case) with proper delaysAll functions check element existence before operating and use the named timing constants consistently.
323-323: Job queue ID extraction is correct.The change properly extracts the queue number from element IDs like
queue_1,queue_2, etc. by splitting on underscore and taking the second element.
672-672: Dialog height increase accommodates enhanced navigation UI.Increasing height from 630 to 800 pixels for copy/move dialogs is appropriate given the addition of the FileTree browser with popular destinations and manual navigation features.
Also applies to: 682-682, 701-701, 709-709, 972-972, 984-984
759-761: Proper event handler cleanup prevents memory leaks.The dialog close handlers correctly remove the namespaced
mousedown.dfmFileTreeevent handlers, complementing the more comprehensive cleanup insetupTargetNavigation(). This prevents memory leaks when dialogs are destroyed.Also applies to: 1036-1038
872-877: Navigation setup correctly scoped to copy/move operations.The calls to
preventFileTreeClose()andsetupTargetNavigation()are properly placed:
preventFileTreeClose()applies to all dialogs to prevent tree closuresetupTargetNavigation()conditionally applies only to copy/move operations (actions 3, 4, 8, 9 indoAction; 3, 4 indoActions)- The additional check for
#dfm_targetexistence ensures the field is present before attaching handlersAlso applies to: 1152-1157
1256-1313: Clipboard integration with graceful HTTP degradation.The rewritten
xlink()function handles clipboard operations well:
- Pre-selects path text to enable manual copying (works on all protocols)
- Attempts automatic clipboard copy via
navigator.clipboard.writeText()on HTTPS- Silent failure on HTTP is intentional (per established learnings) to avoid repetitive warnings
- Shows success tooltip only when clipboard API succeeds
- Terminal button provides additional functionality
Based on learnings, this approach balances functionality with user experience.
378-382: Appropriate error logging in exception handler.The
console.error()statement in the catch block is appropriate production error logging (not debugging output). It captures unexpected failures when showing the tree while preventing the error from propagating to the user.
… class - Changed all warning spans from dfm_text to dfm_warning class - Prevents BrowseButton.page status updates from overwriting warnings - Moved warnings in Copy/Move templates to appear after target input (footer position) - Affected templates: CopyFolder, MoveFolder, CopyFile, MoveFile, CopyObject, MoveObject - All 15 templates with warnings now properly separated from status updates
- Clone dfm_warning from template and add to ui-dialog-buttonpane - Floats left next to Start/Queue/Cancel buttons - Only enabled for action 3 (copy folder) for testing
- Small dialogs (Create/Delete/Rename) now have less empty space - Copy/Move dialogs still expand automatically due to FileTree content - Removes need for per-action height management
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
50-160: LGTM: Excellent concurrency handling and atomic updates.The implementation correctly:
- Uses exclusive file locking for the entire read-modify-write cycle
- Handles file creation, reading, and writing atomically
- Validates input (blocks empty, /mnt, /boot, path traversal)
- Applies decay/increment scoring consistently
- Cleans up properly (unsets reference, releases lock, closes file)
- Logs errors appropriately
The concurrency model is robust and addresses the previous review concern about file locking.
Optional: Stricter path validation
While the current validation is adequate for display-only paths, you could add validation to ensure paths start with
/mnt/or/boot/:// Block path traversal attempts if (strpos($targetPath, '..') !== false) { exec('logger -t webGUI "Security: Blocked path traversal attempt in popular destinations: ' . escapeshellarg($targetPath) . '"'); return; } + + // Validate path starts with /mnt/ or /boot/ + if (!preg_match('#^/(mnt|boot)/#', $targetPath)) { + return; + }This is optional since popular destinations are display-only and can't be used to access files directly. The worst case is storing invalid paths that will naturally decay over time.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/PopularDestinations.phpemhttp/plugins/dynamix/styles/default-dynamix.css
🧰 Additional context used
🧠 Learnings (12)
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/PopularDestinations.php
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-03T02:57:29.994Z
Learnt from: ljm42
Repo: unraid/webgui PR: 2414
File: etc/rc.d/rc.nginx:374-376
Timestamp: 2025-10-03T02:57:29.994Z
Learning: Repo unraid/webgui: In etc/rc.d/rc.nginx, maintainers prefer not to add explicit mv-failure checks or EXIT trap clearing around atomic writes in build_servers(), build_locations(), and build_ini(); treat mv failures (e.g., disk full/permissions) as non-recoverable and keep the implementation simple.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/include/PopularDestinations.php
📚 Learning: 2025-09-03T08:33:04.940Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2352
File: emhttp/plugins/dynamix.plugin.manager/include/PluginHelpers.php:0-0
Timestamp: 2025-09-03T08:33:04.940Z
Learning: In the unraid/webgui codebase, Squidly271 prefers file locking to be handled centrally within the file_put_contents_atomic function rather than in individual functions that use it. This maintains cleaner architecture by centralizing the locking mechanism.
Applied to files:
emhttp/plugins/dynamix/include/PopularDestinations.php
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/styles/default-dynamix.css
🔇 Additional comments (11)
emhttp/plugins/dynamix/styles/default-dynamix.css (3)
1487-1487: LGTM! Improved dialog min-height for compact displays.Reducing the minimum height from 35vh to 20vh improves the mobile/compact display experience while still maintaining a reasonable minimum size for dialog content.
1501-1506: LGTM! Well-scoped warning text styling.The
.dfm-warningstyling is properly scoped within.ui-dialog-buttonpaneand uses CSS variables consistently with the rest of the stylesheet.
1754-1795: Excellent! Previous scoping issue has been resolved.The mobile responsiveness block is well-structured with all rules properly scoped to
.ui-dialogor its descendants. The previous concern about the overly broaddlselector has been addressed—line 1765 now correctly scopes to.ui-dialog dl.Note on browser compatibility: The
:has()pseudo-class (lines 1771, 1776) requires relatively modern browsers (Chrome 105+, Safari 15.4+, Firefox 121+). Given that this is 2026 and Unraid targets modern browsers, this should be acceptable, but ensure your minimum browser requirements align with:has()support.emhttp/plugins/dynamix/include/Control.php (6)
16-16: LGTM: Clean dependency injection.The inclusion of PopularDestinations.php is correctly placed at the top of the file, making the new functions available throughout Control.php.
61-69: LGTM: Variable rename improves clarity.Renaming
$fileto$targetFilein the upload flow makes the code more readable by distinguishing between the file path and the content being written.
113-122: LGTM: JSON parsing with proper validation.The job queue display correctly:
- Skips empty and invalid JSON entries
- Extracts structured fields (task, source, target)
- Maintains proper job numbering
140-170: LGTM: JSON validation loop correctly implemented.The start sequence now properly handles invalid JSON entries by looping through the queue until a valid entry is found, addressing the previous review concern. The implementation correctly:
- Uses a while loop instead of problematic return statement
- Validates JSON before processing
- Cleans up invalid entries
- Manages queue state appropriately
177-196: LGTM: Input validation correctly implemented.The undo operation now properly validates
$_POST['row']values:
- Checks
is_numeric()before processing- Skips invalid entries
- Safely converts 1-based to 0-based indices
- Uses
isset()check beforeunset()This addresses the previous review concern about non-numeric input handling.
206-229: LGTM: Clean integration with PopularDestinations.The file operation handling correctly:
- Builds structured JSON payloads
- Integrates popularity tracking for copy/move operations (actions 3, 4, 8, 9)
- Updates popularity when user makes the decision (both queue and immediate start)
- Validates target is non-empty before updating
The action type comment is accurate per the file_manager switch cases.
emhttp/plugins/dynamix/include/PopularDestinations.php (2)
31-44: LGTM: Appropriate unlocked read for display purposes.The function correctly handles missing or invalid files with sensible defaults. The comment explicitly acknowledges that unlocked reads are acceptable for display, as momentary inconsistency during concurrent writes is tolerable in the UI context.
167-182: LGTM: Clean implementation with defensive programming.The function correctly retrieves and limits the top N destinations. The redundant sort (acknowledged in the comment) is good defensive programming with negligible performance impact for the small dataset size (max 50 entries).
|
Ok, looks fine now. Ready to merge 😁 |
|
Will fix the conflicts... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @emhttp/plugins/dynamix/include/Control.php:
- Line 231: The code uses magic numbers for action types when setting 'action'
=> (int)($_POST['action'] ?? 0) and later when updating popular destinations;
define descriptive constants (e.g., ACTION_COPY_FOLDER, ACTION_MOVE_FOLDER,
ACTION_COPY_FILE, ACTION_MOVE_FILE) in the same class or a central constants
file and replace all numeric literals (3,4,8,9) with those constants; update the
existing comment near line 250 to reference the new constant names and ensure
any comparisons or switch/case use the constants instead of raw integers so the
logic around the popular destinations update remains identical but more
maintainable.
🧹 Nitpick comments (6)
emhttp/plugins/dynamix/include/Control.php (1)
167-182: Good robustness improvement with JSON validation.The validation loop correctly handles corrupt job queue data by skipping invalid JSON entries until finding a valid one or exhausting the list. Proper cleanup occurs when no valid entries remain.
Consider adding logging when invalid JSON is encountered to aid debugging if queue corruption occurs in production.
📝 Optional: Add logging for skipped invalid JSON
while (!empty($lines)) { $data = json_decode($lines[0], true); if ($data) { // Valid JSON found, use it break; } // Invalid JSON, remove this entry and try next + exec('logger -t webGUI "Warning: Skipped invalid JSON in file manager job queue"'); array_shift($lines); }emhttp/plugins/dynamix/Browse.page (5)
544-562: Review timing assumptions.The function uses a 100ms timeout before simulating a click to reload the tree. This timing assumption might not hold on slower systems or under load. Consider:
- Using a callback or event-based approach instead of a fixed timeout
- Adding error handling if the tree container or target doesn't exist
The indirect reset mechanism (relying on
fileTreeAttachchecking ifhtml()is empty) is fragile and depends on external implementation details.
564-593: Consider more robust navigation completion tracking.The timeout calculation
parts.length * FOLDER_EXPAND_DELAY + NAVIGATION_BUFFERassumes all folder expansions take exactlyFOLDER_EXPAND_DELAYms. In practice:
- Faster expansions leave the
isProgrammaticNavigationflag set unnecessarily- Slower expansions reset the flag prematurely, allowing input events to interfere
Consider using a callback or promise-based approach to reset the flag only when navigation truly completes.
595-618: Add error handling or logging for failed navigation.The function silently fails if a folder is not found (line 601), providing no feedback to the user or calling code. Consider:
- Logging when navigation cannot proceed
- Calling an error callback to notify the user
- Adding depth limits to prevent unbounded recursion with very deep paths
669-669: Replace inline styles with a CSS class.The repeated
margin-bottom: 320pxinline style is applied six times. Consider:
- Defining a CSS class (e.g.,
.dfm-target-with-tree) with the appropriate margin- Adding the class instead of inline styles:
$target.addClass('dfm-target-with-tree')- Documenting why 320px is the appropriate value
This improves maintainability and makes responsive adjustments easier.
Also applies to: 679-679, 696-696, 704-704, 982-982, 995-995
1363-1391: Consider extracting styles to CSS.The textarea has extensive inline styles defined in JavaScript (line 1340). Consider:
- Moving these styles to a CSS class (e.g.,
.dfm-path-textarea)- This improves maintainability and allows for easier responsive adjustments
- The 100ms setTimeout (line 1363) before select/focus might be too short on slower devices
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.php
🧰 Additional context used
🧠 Learnings (15)
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-10-03T02:57:29.994Z
Learnt from: ljm42
Repo: unraid/webgui PR: 2414
File: etc/rc.d/rc.nginx:374-376
Timestamp: 2025-10-03T02:57:29.994Z
Learning: Repo unraid/webgui: In etc/rc.d/rc.nginx, maintainers prefer not to add explicit mv-failure checks or EXIT trap clearing around atomic writes in build_servers(), build_locations(), and build_ini(); treat mv failures (e.g., disk full/permissions) as non-recoverable and keep the implementation simple.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(50-160)
🔇 Additional comments (9)
emhttp/plugins/dynamix/include/Control.php (2)
16-16: LGTM: Dependency properly added for popular destinations feature.The require statement is correctly placed and follows the existing pattern. The PopularDestinations.php module provides the updatePopularDestinations function used later in the file.
201-208: LGTM: Proper input validation prevents non-numeric row indices.The validation correctly ensures only numeric job indices are processed, preventing potential issues with array access. The explicit integer cast adds type safety.
emhttp/plugins/dynamix/Browse.page (7)
259-259: LGTM: Consistent dialog styling applied.The
ui-corner-allclass addition provides consistent rounded corners across all File Manager dialogs.Also applies to: 302-302, 743-743, 1036-1036
354-356: LGTM: Navigation timing constants defined.The delay constants provide configurable timing for folder expansion. The values (300ms per folder, 500ms buffer) seem reasonable for UI responsiveness.
524-542: LGTM: Clean folder closing logic.The function properly closes folders by updating classes and removing child elements. The implementation is straightforward and focused.
664-664: LGTM: File tree configuration via data attributes.The data attributes properly configure the file tree behavior for different action types (copy/move). The
SHOW_POPULARandHIDE_FILES_FILTERvalues integrate well with the Popular Destinations feature.Also applies to: 674-674, 693-693, 701-701, 975-976, 988-989
885-889: LGTM: Targeted navigation setup.The calls to
setupTargetNavigation()are properly scoped to copy/move operations (actions 3, 4, 8, 9) and include defensive checks for target element existence. The integration is clean and consistent between single and bulk operations.Also applies to: 1177-1181
753-773: The CSS classdfm-warningis properly defined with complete styling inemhttp/plugins/dynamix/styles/default-dynamix.css. All concerns raised are already addressed:
- Positioning: Uses
inline-blockwithvertical-align: middleon desktop, responsiveblocklayout on mobile- Text wrapping: Media query provides full responsive handling with
width: 100%on narrow screens- Contrast: Uses CSS variable
--alt-text-colorfor theme-aware contrast- Mobile responsiveness: Explicit media query styling ensures proper display across all screen sizes
No action needed.
Likely an incorrect or invalid review comment.
1335-1392: openTerminal() function is properly available and correctly implemented.The
openTerminal()function is defined inemhttp/plugins/dynamix/include/DefaultPageLayout/HeadInlineJS.php(line 158) and is globally available to all pages including Browse.page through the DefaultPageLayout include. The function signatureopenTerminal(tag, name, more)correctly matches the xlink() call pattern, with the path parameter properly passed as themoreargument to OpenTerminal.php for terminal initialization.The clipboard functionality's silent failure on HTTP connections is intentional design—the path text is pre-selected to allow manual copying as a fallback.
All button handlers now call dialog('close') before dialog('destroy')
to ensure the dialogclose event fires and cleanup code executes.
This fixes a memory leak where document-level listeners (treeClickHandler,
popularClickHandler) and input element listeners were never removed because
dialog('destroy') does not trigger the dialogclose event.
Addresses code review feedback on PR unraid#2500.
The dir parameter comes URL-encoded from the browser (e.g., %22 for quotes, %0A for newlines). htmlspecialchars_decode() only decodes HTML entities (") but not URL encoding. This caused paths with special characters to fail validation in validdir() because realpath() received URL-encoded strings like 'foo%22bar' instead of 'foo"bar'. Solution: Apply rawurldecode() before htmlspecialchars_decode() to properly decode both URL encoding and HTML entities. Fixes: - /mnt/disk1/test/foo"bar (URL: %2Fmnt%2Fdisk1%2Ftest%2Ffoo%22bar) - /mnt/disk1/test/foo\nbar (URL: %2Fmnt%2Fdisk1%2Ftest%2Ffoo%0Abar)
Fixes three related issues with special characters in paths: 1. Browse.php: Add htmlspecialchars_decode() - Browse.page escapes paths with htmlspecialchars() for JavaScript - AJAX calls to Browse.php sent escaped strings (" instead of ") - realpath() couldn't find folders with quotes in their names 2. Browse.page: Escape newlines/tabs for JavaScript - Paths with \n, \r, \t caused JavaScript syntax errors - JavaScript: var dir = "/path/with\nNewline"; broke the page - Now properly escaped to \\n, \\r, \\t for JavaScript strings 3. Browse.page: Add rawurldecode() for consistency - PHP auto-decodes , but explicit decode improves clarity - Matches Browse.php pattern for URL parameter handling Test cases now working: - /mnt/disk1/test/foo"bar - /mnt/disk1/test/foo\nbar (newline in filename) - /mnt/disk1/test/foo\\\"bar (backslash + quote) These are pre-existing bugs discovered during unraid#2500 testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @emhttp/plugins/dynamix/Browse.page:
- Line 667: Replace the incorrect attribute data-show-popular='true' on the
dfm.window.find('#dfm_target') call with data-pickfilter='SHOW_POPULAR' so that
fileTreeAttach() reads the filter via jQuery .data('pickfilter'); specifically
update the chained attr(...) call on the element selected by
dfm.window.find('#dfm_target') in the invocation that sets data-pickroot,
data-picktop, data-pickmatch so it uses data-pickfilter='SHOW_POPULAR' to match
the other instances and enable the popular-destinations behavior.
- Around line 31-33: The $dir value is being HTML-escaped with
htmlspecialchars() which produces entities that the HTML parser will convert
back before JS runs, breaking the inline JS assignment var dir = "<?=$dir?>";
instead, keep the existing decoding/normalization
(validdir(htmlspecialchars_decode(rawurldecode($dir))) / my_explode(...)) but
when preparing $dir for injection into JavaScript replace the htmlspecialchars()
re-encoding with a JS-safe escape such as json_encode($dir) (or at minimum
addslashes($dir)) so the embedded var dir gets a properly quoted/escaped JS
string; update the code that constructs $dir for the inline script (the variable
used in var dir = "<?=$dir?>") to use json_encode() output (or use a PHP
variable like $dir_js = json_encode($dir) and embed that) instead of
htmlspecialchars().
In @emhttp/plugins/dynamix/include/Browse.php:
- Line 136: The code decodes HTML entities via htmlspecialchars_decode() before
validating the path, which is unnecessary for filesystem paths and risks
altering input prior to validation; remove htmlspecialchars_decode() and pass
rawurldecode($_GET['dir']) directly into validdir() (e.g., change the call that
currently uses htmlspecialchars_decode(rawurldecode($_GET['dir'])) to just
rawurldecode($_GET['dir'])) and apply the same change in Browse.page where the
same pattern appears (ensure validdir(), realpath-based checks, and subsequent
escapeshellarg()/HTML escaping remain unchanged).
🧹 Nitpick comments (3)
emhttp/plugins/dynamix/Browse.page (3)
361-525: Review complex event handling for potential race conditions and cleanup.The
setupTargetNavigation()function implements sophisticated file tree navigation with capture-phase event handlers and multiple state flags. A few observations:
Event listener cleanup (lines 516-524): Good that capture-phase listeners are removed on dialog close. Verify this cleanup happens in all dialog close scenarios (cancel, success, escape key).
Race condition potential (lines 460-461, 508-509): Multiple flags prevent overlapping navigation (
isNavigatingFromPopular,isProgrammaticNavigation), but verify these flags are always set/cleared correctly across all code paths.Timeout management (line 474):
clearTimeout(navigationTimeout)is called, but verify no timeout leaks if the dialog closes before the timeout fires.Event propagation (lines 373-392): The
preventClosefunction usesstopImmediatePropagation()which is very aggressive and could interfere with other handlers. Consider whether this is necessary or if a more targeted approach would work.Consider refactoring to:
- Consolidate state flags into a single state object for easier tracking
- Add a cleanup function that's called on dialog close to ensure all timeouts are cleared
- Document the event handler precedence and why capture phase is needed
598-621: Consider adding safeguards to the recursive folder expansion.The
openFolderRecursive()function uses recursivesetTimeout()calls to expand folders in sequence. This is functional but consider:
No depth limit: If a malicious or misconfigured path has many levels, this could create many pending timeouts. Consider adding a maximum depth check.
No cancellation mechanism: If the user closes the dialog or navigates away, pending timeouts will still fire. These should be tracked and cleared on cleanup.
Hard-coded delay (line 619):
FOLDER_EXPAND_DELAYof 300ms might be too slow for local filesystems or too fast for network mounts. Consider making this configurable or adaptive.Suggested improvements
Track pending timeouts for cleanup:
var navigationTimeouts = []; function openFolderRecursive($tree, pickroot, parts, index, maxDepth = 50) { if (index >= parts.length || index >= maxDepth) return; // ... existing logic ... var timeoutId = setTimeout(function() { openFolderRecursive($tree, pickroot, parts, index + 1, maxDepth); }, FOLDER_EXPAND_DELAY); navigationTimeouts.push(timeoutId); } // In cleanup: navigationTimeouts.forEach(clearTimeout); navigationTimeouts = [];
756-776: Consider extracting warning injection logic to reduce duplication.The warning text injection logic is duplicated between
doAction()(lines 756-776) anddoActions()(lines 1051-1067). The logic is identical:
- Define
warningTextsmapping- Get warning text for current action
- Create and prepend warning div
Refactoring suggestion
Extract to a shared function:
function addDialogWarning(action) { var warningTexts = { // ... other warnings }; var warningText = warningTexts[action]; if (warningText) { var $warning = $('<div class="dfm-warning">').html('<i class="fa fa-warning dfm"></i> ' + warningText); $('.ui-dfm .ui-dialog-buttonset').prepend($warning); } }Then call
addDialogWarning(action);in both dialog open handlers.Also applies to: 1051-1067
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Browse.php
🧰 Additional context used
🧠 Learnings (8)
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Browse.php
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🔇 Additional comments (3)
emhttp/plugins/dynamix/Browse.page (3)
892-894: LGTM - setupTargetNavigation is called for appropriate actions.The navigation setup is correctly applied:
- Lines 892-894: Single item operations (actions 3, 4, 8, 9 = copy/move folder/file)
- Lines 1186-1188: Bulk operations (actions 3, 4 = copy/move objects)
The bulk handler doesn't need to check for actions 8 and 9 because those are file-specific single-item operations, while bulk operations handle mixed types as "objects."
Also applies to: 1186-1188
1369-1398: LGTM - Good UX implementation for path display and copy.The textarea implementation provides good mobile support and proper clipboard handling:
- Auto-selects text for easy manual copying
- Attempts clipboard API if available (HTTPS only)
- Silently falls back to manual copy if clipboard fails
- Shows success tooltip when copy works
- Clean timeout-based cleanup
Based on learnings, the silent fail behavior for HTTP connections is intentional and preferred over showing warnings.
1342-1399: Path sanitization in openTerminal() is properly handled—no security issue.The
openTerminal()call on line 1360 passes the path through PHP'srealpath()function (OpenTerminal.php:62), which only returns a valid result for existing filesystem paths and returns FALSE for non-existent paths (falling back safely to/root). Filesystem paths cannot contain shell metacharacters by design, so the threat model in the review comment (backticks, semicolons, shell metacharacters) is not applicable. Additionally, proper escaping is applied for both shell (single quote escaping) and sed contexts (lines 70–72 in OpenTerminal.php) before the path is used in the command. No code changes are needed.Likely an incorrect or invalid review comment.
Address all mandatory code review feedback and fix special character handling: CODE REVIEW FIXES: - Remove htmlspecialchars_decode() from Browse.page line 31 (not needed, causes issues) - Use json_encode() with JSON_UNESCAPED_SLASHES for JavaScript context escaping - Extract addActionWarning() function to reduce code duplication - Replace data-show-popular with data-pickfilter='SHOW_POPULAR' - Extract inline margin-bottom styles to .dfm-target-with-tree CSS class - Extract xlink textarea styles to .dfm-path-textarea CSS class - Add syslog warning for invalid JSON in job queue validation AMPERSAND HANDLING FIXES: - Fix Browse.php: Use htmlspecialchars() for data attributes (escape & to &) - Fix BrowseButton.page: Use jQuery .text() for auto-escaping in select options - Fix FileTree.php: Keep htmlspecialchars() for rel attributes (HTML context) - Fix Control.php: Remove unnecessary htmlspecialchars_decode() calls RESULT: All special characters including ampersands (&) now work correctly: - Files/folders with & in name can be deleted/moved/copied - Visual display shows correct literal names (foo&bar) - FileTree navigation works with ampersand folders - Select boxes display correctly This completes all code review requirements for PR unraid#2500.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
emhttp/plugins/dynamix/include/Control.php (2)
201-214: Tightenundorow validation: preferctype_digitand>= 1.
is_numericallows1.9,1e3,-1;(int)then silently changes meaning and can remove the wrong job.Proposed fix
if (file_exists($jobs)) { - $rows = explode(',',$_POST['row']); + $rows = explode(',', $_POST['row'] ?? ''); $lines = file($jobs, FILE_IGNORE_NEW_LINES); foreach ($rows as $row) { - // Validate and convert to integer to prevent non-numeric input - if (!is_numeric($row)) { - continue; // Skip invalid entries - } - $row = (int)$row; + $row = trim($row); + if ($row === '' || !ctype_digit($row)) continue; + $row = (int)$row; + if ($row < 1) continue; $line_number = $row - 1; // Convert 1-based job number to 0-based array index if (isset($lines[$line_number])) { unset($lines[$line_number]); } }
231-255: Update Popular Destinations when a job starts, not when it’s enqueued/created.
Right now Line 252 updates popularity even for queued jobs that might be undone/cancelled/failed. More accurate: update in the “start operation” path (notask) and when dequeuing inmode=start.Proposed fix (move side-effect)
if (isset($_POST['task'])) { // add task to queue $data['task'] = rawurldecode($_POST['task']); file_put_contents($jobs, json_encode($data)."\n", FILE_APPEND); } else { // start operation file_put_contents($active, json_encode($data)); - } - - // Update popular destinations for copy/move operations - // Action types: 3=copy folder, 4=move folder, 8=copy file, 9=move file - if (in_array((int)$data['action'], [3, 4, 8, 9]) && !empty($data['target'])) { - updatePopularDestinations($data['target']); + // Update popular destinations only when an operation actually starts + // Action types: 3=copy folder, 4=move folder, 8=copy file, 9=move file + if (in_array((int)$data['action'], [3, 4, 8, 9]) && !empty($data['target'])) { + updatePopularDestinations($data['target']); + } }And in
case 'start'after you’ve found valid$data/$lines[0], update before writing$active:if (in_array((int)($data['action'] ?? 0), [3,4,8,9]) && !empty($data['target'] ?? '')) { updatePopularDestinations($data['target']); }
🧹 Nitpick comments (5)
emhttp/plugins/dynamix/Browse.page (2)
389-392: Consider documenting timing constant rationale.The constants
FOLDER_EXPAND_DELAY = 300andNAVIGATION_BUFFER = 500work for the current implementation, but adding a comment explaining why these specific values were chosen would help future maintainers understand if they can be adjusted.📝 Suggested documentation improvement
// File tree navigation constants -var FOLDER_EXPAND_DELAY = 300; // Delay per folder expansion in openFolderRecursive (ms) -var NAVIGATION_BUFFER = 500; // Additional buffer time for navigation completion (ms) +var FOLDER_EXPAND_DELAY = 300; // Delay per folder expansion in openFolderRecursive (ms) - allows DOM updates to complete +var NAVIGATION_BUFFER = 500; // Additional buffer time for navigation completion (ms) - ensures all async operations finish
579-597: Minor: Consider if 100ms delay is sufficient for tree reload.Line 595 uses a 100ms
setTimeoutbefore triggering the click to reload the tree. This should work in most cases, but on slower devices or with heavy DOM, it might not be enough time for the empty operation to complete.Consider using
requestAnimationFrameor checking if the container is empty before clicking:♻️ Alternative approach
function resetFileTree($target) { var $treeContainer = $target.siblings('.fileTree'); if ($treeContainer.length === 0) { return; } $treeContainer.hide(); $treeContainer.empty(); - setTimeout(function() { + requestAnimationFrame(function() { $target.click(); - }, 100); + }); }emhttp/plugins/dynamix/include/Control.php (3)
14-16: Guard the newPopularDestinations.phpinclude (optional hardening).
If a user hits this endpoint during a partial/failed update,require_oncewill fatal. Consider a defensivefile_exists+loggerfallback if that’s a realistic state for Unraid upgrades.
96-99: Add defaults for$_POST['source']/$_POST['target']to avoid notices.
rawurldecode($_POST['source'])/rawurldecode($_POST['target'])will emit notices if keys are missing; other modes already use??.Also applies to: 123-130
163-195: Avoid O(n²)array_shiftloop + log spam when skipping invalid JSON.
Current loop shifts the array repeatedly and logs once per bad line. Consider scanning with an index, slicing once, and logging a single warning with a count.Proposed refactor
$lines = file($jobs, FILE_IGNORE_NEW_LINES); if (!empty($lines)) { - // Skip invalid JSON entries (loop until we find valid JSON or run out of entries) - while (!empty($lines)) { - $data = json_decode($lines[0], true); - if ($data) { - // Valid JSON found, use it - break; - } - // Invalid JSON, remove this entry and try next - exec('logger -t webGUI "Warning: Skipped invalid JSON in file manager job queue"'); - array_shift($lines); - } + // Skip invalid JSON entries (scan once, slice once) + $skipped = 0; + $data = null; + for ($i = 0, $n = count($lines); $i < $n; $i++) { + $data = json_decode($lines[$i], true); + if ($data) break; + $skipped++; + } + if ($skipped > 0) { + exec('logger -t webGUI "Warning: Skipped '.$skipped.' invalid JSON entr'.($skipped===1?'y':'ies').' in file manager job queue"'); + $lines = array_slice($lines, $skipped); + } if (empty($lines)) { // No valid JSON entries found delete_file($jobs); die('0'); }
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/BrowseButton.pageemhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/styles/default-dynamix.css
🧰 Additional context used
🧠 Learnings (17)
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Browse.phpemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/BrowseButton.pageemhttp/plugins/dynamix/styles/default-dynamix.css
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-07-11T17:24:33.977Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2293
File: emhttp/plugins/dynamix.docker.manager/include/Helpers.php:302-304
Timestamp: 2025-07-11T17:24:33.977Z
Learning: In the Unraid WebGUI Docker manager (emhttp/plugins/dynamix.docker.manager/include/Helpers.php), the xmlSecurity() function call is intentionally commented out to allow users to include < and > characters in their Docker template variables on their own servers. Default templates still explicitly disallow tags, but users can customize templates as needed in their self-hosted environment.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-03T02:57:29.994Z
Learnt from: ljm42
Repo: unraid/webgui PR: 2414
File: etc/rc.d/rc.nginx:374-376
Timestamp: 2025-10-03T02:57:29.994Z
Learning: Repo unraid/webgui: In etc/rc.d/rc.nginx, maintainers prefer not to add explicit mv-failure checks or EXIT trap clearing around atomic writes in build_servers(), build_locations(), and build_ini(); treat mv failures (e.g., disk full/permissions) as non-recoverable and keep the implementation simple.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-10T21:55:43.944Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-06-10T21:55:43.944Z
Learning: For the unraid/webgui repository, the target browsers fully support the CSS :has() pseudo-class; future reviews should not raise compatibility or “nitpick” comments about using :has().
Applied to files:
emhttp/plugins/dynamix/styles/default-dynamix.css
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(50-160)
🔇 Additional comments (11)
emhttp/plugins/dynamix/include/Browse.php (1)
231-231: LGTM! Improved HTML attribute encoding.The switch from
escapeQuote()tohtmlspecialchars($name, ENT_QUOTES, 'UTF-8')is a security improvement that properly escapes ampersands, quotes, and other special characters in filenames. This aligns with the PR's objective to correct handling of filenames containing&and other special characters.Also applies to: 250-250
emhttp/plugins/dynamix/BrowseButton.page (1)
131-146: LGTM! Safer DOM manipulation pattern.The refactoring from HTML string concatenation to jQuery DOM creation with
.text()properly escapes filenames and prevents potential XSS. The use ofselect.empty()at the start ensures a clean slate before repopulating options.emhttp/plugins/dynamix/styles/default-dynamix.css (3)
1487-1487: LGTM! Improved mobile dialog sizing.Reducing min-height from 35vh to 20vh provides better mobile UX by preventing unnecessary whitespace in dialogs with less content.
1500-1521: LGTM! Well-documented new styles for file tree navigation.The new classes
dfm-target-with-treeanddfm-path-textareaare well-commented with clear explanations of their purpose and values (e.g., 320px accommodates typical tree height).
1777-1818: No action needed. The mobile dialog improvements block appears only once in the stylesheet (line 1777). There is no duplicate block elsewhere in the file.Likely an incorrect or invalid review comment.
emhttp/plugins/dynamix/Browse.page (5)
31-35: LGTM! Proper encoding for JavaScript injection.The change from
htmlspecialchars_decode()torawurldecode()is more semantically correct for URL-encoded paths. Usingjson_encode()with appropriate flags for the JavaScript context properly escapes quotes, backslashes, and newlines while keeping paths readable. The clear comments explain the rationale.Also applies to: 49-49
62-91: LGTM! Clear warning display implementation.The
addActionWarning()function provides helpful user context for file operations. The distinction between bulk and non-bulk warning texts is appropriate, and all strings are properly localized.
393-557: LGTM! Comprehensive navigation setup with proper cleanup.The
setupTargetNavigation()function properly handles:
- Capture-phase event listeners to prevent fileTree closure
- Popular destinations click handling
- Input-driven navigation with debouncing
- Programmatic navigation state tracking
- Proper cleanup on dialog close (lines 548-556) removes all event listeners
The use of capture phase (
addEventListenerwithtrue) is appropriate to intercept events before the fileTree's handlers.
699-715: LGTM! Consistent integration of file tree navigation.The file tree navigation features are properly integrated into copy/move dialogs:
data-pickfilter='SHOW_POPULAR'enables popular destinationsdfm-target-with-treeclass provides appropriate spacing (320px margin)setupTargetNavigation()is called only for copy/move operations (actions 3, 4, 8, 9)addActionWarning()provides user contextThe integration is consistent across both
doAction()anddoActions().Also applies to: 728-740, 788-790, 904-909
1357-1414: LGTM! Improved mobile support and user experience.The reworked
xlink()function provides several improvements:
- Textarea with auto-selection works better on mobile than input fields
- Clipboard API integration provides one-click copy on HTTPS (silently fails on HTTP per learnings)
- Success feedback tooltip confirms copy action
- Terminal button integration for "Open Terminal here" feature
- Unique ID generation prevents conflicts with multiple dialogs
Based on learnings, the silent clipboard failure on HTTP without warnings is intentional to avoid annoying HTTP users who can still manually copy the pre-selected text.
emhttp/plugins/dynamix/include/Control.php (1)
48-52:rawurldecode(...)+validname(...)for upload path looks correct.
Usingrawurldecode(noturldecode) avoids+→ space surprises and thevalidnamegate keeps roots constrained.
Control.php improvements: - Use ctype_digit() instead of is_numeric() for undo row validation Prevents accepting floats (1.9), scientific notation (1e3), or negatives (-1) - Update popular destinations only when jobs actually start Move updatePopularDestinations() to job execution (not queue creation) Prevents tracking popularity for cancelled/failed jobs - Add null coalescing operators (??) for $_POST['source'] and $_POST['target'] Avoids PHP notices when parameters are missing - Optimize invalid JSON scanning to avoid O(n²) complexity Replace array_shift() loop with index-based scan and single array_slice() Log once with count instead of spamming per entry - Prevent path traversal in 'stop' mode Use basename() to strip directory components and prevent ../escapes Only delete if filename is not empty Browse.page improvements: - Add rationale comments for FOLDER_EXPAND_DELAY and NAVIGATION_BUFFER - Use requestAnimationFrame() instead of setTimeout() in resetFileTree() Semantically correct for DOM operations, waits for browser render cycle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/Browse.page (1)
1065-1081: Consider usingaddActionWarningto avoid duplication.The warning text lookup in this
opencallback duplicates the logic already present inaddActionWarning(). SinceaddActionWarningalready supports theisBulkparameter, you can simplify this:♻️ Suggested refactor
open: function() { - // Add warning to buttonpane for all relevant actions (bulk operations) - var warningTexts = { - 0: "<?=_("This creates a folder at the current level")?>", - 1: "<?=_("This deletes all selected sources")?>", - 2: "<?=_("This renames the selected source")?>", - 3: "<?=_("This copies all the selected sources")?>", - 4: "<?=_("This moves all the selected sources")?>", - 11: "<?=_("This changes the owner of the source recursively")?>", - 12: "<?=_("This changes the permission of the source recursively")?>" - }; - var warningText = warningTexts[action]; - if (warningText) { - var $warning = $('<div class="dfm-warning">').html('<i class="fa fa-warning dfm"></i> ' + warningText); - $('.ui-dfm .ui-dialog-buttonset').prepend($warning); - } + addActionWarning(action, true); },
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
emhttp/plugins/dynamix/Browse.pageemhttp/plugins/dynamix/include/Control.php
🧰 Additional context used
🧠 Learnings (17)
📚 Learning: 2025-08-14T23:53:38.384Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2338
File: emhttp/plugins/dynamix/nchan/parity_list:151-151
Timestamp: 2025-08-14T23:53:38.384Z
Learning: In the unraid/webgui codebase, the parity_list nchan script always JSON-encodes the $echo payload when publishing to the 'parity' channel, regardless of whether $echo is an array or string. This is the pre-existing behavior and consumers are designed to handle JSON-encoded payloads appropriately.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-10-22T17:36:50.995Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-10-22T17:36:50.995Z
Learning: In the Unraid webgui codebase, when adjusting CPU pinning, 3rd party containers without template files do not appear in the list. Therefore, silently skipping non-existent template files without logging is the appropriate behavior in UpdateOne.php.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-02-27T21:50:34.913Z
Learnt from: dlandon
Repo: unraid/webgui PR: 2035
File: emhttp/plugins/dynamix/scripts/syslogfilter:45-48
Timestamp: 2025-02-27T21:50:34.913Z
Learning: The syslog filter script in the unraid/webgui repository does not require explicit error handling for the rsyslog service restart. The simple approach without additional error checking is sufficient for this implementation.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-10-03T02:57:29.994Z
Learnt from: ljm42
Repo: unraid/webgui PR: 2414
File: etc/rc.d/rc.nginx:374-376
Timestamp: 2025-10-03T02:57:29.994Z
Learning: Repo unraid/webgui: In etc/rc.d/rc.nginx, maintainers prefer not to add explicit mv-failure checks or EXIT trap clearing around atomic writes in build_servers(), build_locations(), and build_ini(); treat mv failures (e.g., disk full/permissions) as non-recoverable and keep the implementation simple.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:00.594Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php:58-74
Timestamp: 2025-03-27T22:04:00.594Z
Learning: The file `emhttp/plugins/dynamix.my.servers/include/activation-code-extractor.php` is synced from a different repository, and modifications should not be suggested in this repository's context. Changes should be proposed in the source repository instead.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/include/Control.phpemhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.
Applied to files:
emhttp/plugins/dynamix/include/Control.php
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-07-11T17:24:33.977Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2293
File: emhttp/plugins/dynamix.docker.manager/include/Helpers.php:302-304
Timestamp: 2025-07-11T17:24:33.977Z
Learning: In the Unraid WebGUI Docker manager (emhttp/plugins/dynamix.docker.manager/include/Helpers.php), the xmlSecurity() function call is intentionally commented out to allow users to include < and > characters in their Docker template variables on their own servers. Default templates still explicitly disallow tags, but users can customize templates as needed in their self-hosted environment.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T02:06:47.712Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/nchan/parity_list:150-158
Timestamp: 2025-08-13T02:06:47.712Z
Learning: In the unraid/webgui codebase, the publish() and publish_noDupe() functions in emhttp/plugins/dynamix/include/publish.php automatically handle JSON encoding when arrays are passed to them, eliminating the need for manual json_encode() calls at the call sites.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/Control.php (1)
emhttp/plugins/dynamix/include/PopularDestinations.php (1)
updatePopularDestinations(50-160)
🔇 Additional comments (25)
emhttp/plugins/dynamix/include/Control.php (9)
16-16: LGTM!The inclusion of
PopularDestinations.phpis correctly placed and follows the existing include pattern in the file.
48-48: LGTM!Removing
htmlspecialchars_decodeis appropriate since the client should send URL-encoded paths, not HTML-encoded values. The path still passes throughvalidname()for validation.
156-158: Good security hardening.Using
basename()to strip directory components is a robust defense against path traversal, ensuring only the filename is used when constructing the temp file path. This is simpler and more explicit than relying onvalidname().
168-190: Well-structured JSON validation with appropriate cleanup.The implementation efficiently scans for valid JSON entries, logs skipped entries with proper singular/plural grammar, and correctly handles the edge case where no valid entries remain. The popular destinations update is appropriately triggered when dequeuing jobs for execution.
209-215: Solid input validation.Using
trim(), empty check, andctype_digit()before casting provides robust protection against malformed input. The validation correctly handles edge cases like '0' (skipped since job numbers are 1-based).
238-241: LGTM!Casting
actiontointensures type safety, and the input decoding is consistent with other changes throughout the file.
254-259: Correct integration of popular destinations tracking.The popular destinations update is appropriately triggered for immediate operations, complementing the queued job handling on lines 188-190. This ensures all copy/move operations are tracked regardless of execution path.
97-97: LGTM!The input decoding change is consistent with the file-wide refactoring, and the value is still sanitized through
quoted()before shell usage.
124-125: LGTM!Consistent input decoding changes. Both
sourceandtargetare properly sanitized throughquoted()before being used in shell commands.emhttp/plugins/dynamix/Browse.page (16)
31-35: LGTM! Proper encoding for JavaScript context.Using
json_encode()with these flags is the correct approach to safely inject PHP values into JavaScript, preventing XSS from paths containing quotes, backslashes, or other special characters.
49-49: LGTM!Correct usage of the JSON-encoded value for safe JavaScript variable assignment.
62-91: LGTM! Clean implementation of action warnings.The function is well-structured with proper localization. The object-based lookup is cleaner than a switch statement, and the undefined check on line 86 correctly handles actions that don't need warnings.
393-557: Well-structured navigation implementation with proper cleanup.The use of capture-phase event listeners is appropriate for intercepting events before the fileTree's handlers. The cleanup logic in
dialogclose(lines 548-556) properly removes all document-level listeners, preventing memory leaks.One minor observation: the empty
elseblock at lines 502-504 could be removed or consolidated with a comment, but it doesn't affect functionality.
559-577: LGTM!Clean implementation for closing folder paths in the tree. Properly handles trailing slashes and DOM manipulation.
579-597: LGTM!Good use of
requestAnimationFrameto ensure DOM updates complete before triggering the reload. The comment at line 593 clarifies the reload mechanism.
599-628: LGTM!The navigation logic correctly validates paths, splits them into components, and manages the programmatic navigation state. The timeout calculation at line 627 appropriately accounts for the async nature of folder expansion.
630-653: LGTM!The recursive folder expansion is well-implemented with appropriate delays to allow DOM updates between expansions.
699-714: LGTM!Consistent application of the
SHOW_POPULARfilter and styling class for copy/move folder dialogs.
728-739: LGTM!Consistent with the folder copy/move changes.
778-909: LGTM! Clean dialog lifecycle management.The
opencallback is the correct place to inject warnings after the dialog is fully rendered. Addingdialog('close')beforedestroy()ensures proper event cleanup.
994-1014: LGTM!The conditional filter logic is appropriate:
HIDE_FILES_FILTERfor directory/bulk operations (where users pick destination folders) and file-visible filter for single file operations.
1184-1204: LGTM!Consistent dialog lifecycle pattern with proper navigation setup for bulk copy/move operations.
1357-1414: LGTM! Good implementation of copy-to-clipboard with terminal integration.The design correctly handles:
- Silent clipboard fail on HTTP connections (user can still manually copy the pre-selected text)
- SweetAlert callback semantics:
isConfirm === falsecorrectly identifies only the Terminal button click, ignoring dismissalsBased on learnings, the silent fail behavior is intentional to avoid repetitive error messages for HTTP users.
291-311: LGTM!Consistent dialog styling and lifecycle cleanup pattern applied to the file editor dialog.
336-377: LGTM!Consistent styling and lifecycle pattern applied to the jobs dialog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
README.md (1)
35-35: Weaken the intensifier on line 35.Replace "very large directories" with more concrete language (e.g., "large directories", "deeply nested directories", or a specific size/depth threshold if known).
emhttp/plugins/dynamix/Browse.page (1)
637-660: Consider using.closest('li')for robustness.Line 645 uses
$folderLink.parent()which assumes the<a>element is a direct child of<li>. If the jqueryFileTree plugin's HTML structure changes, this could break.♻️ Suggested improvement
- var $folderLi = $folderLink.parent(); + var $folderLi = $folderLink.closest('li');
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
README.mdemhttp/plugins/dynamix/Browse.page
🧰 Additional context used
🧠 Learnings (10)
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-03-27T22:04:34.550Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2099
File: emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php:13-19
Timestamp: 2025-03-27T22:04:34.550Z
Learning: The file emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php is synced from another repository and should not be modified directly in the webgui repository.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-07-11T17:24:33.977Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2293
File: emhttp/plugins/dynamix.docker.manager/include/Helpers.php:302-304
Timestamp: 2025-07-11T17:24:33.977Z
Learning: In the Unraid WebGUI Docker manager (emhttp/plugins/dynamix.docker.manager/include/Helpers.php), the xmlSecurity() function call is intentionally commented out to allow users to include < and > characters in their Docker template variables on their own servers. Default templates still explicitly disallow tags, but users can customize templates as needed in their self-hosted environment.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T02:06:47.712Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/nchan/parity_list:150-158
Timestamp: 2025-08-13T02:06:47.712Z
Learning: In the unraid/webgui codebase, the publish() and publish_noDupe() functions in emhttp/plugins/dynamix/include/publish.php automatically handle JSON encoding when arrays are passed to them, eliminating the need for manual json_encode() calls at the call sites.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🪛 LanguageTool
README.md
[style] ~35-~35: As an alternative to the over-used intensifier ‘very’, consider replacing this phrase.
Context: ...ishes - Use timeout to prevent hangs on very large directories Challenge: For move op...
(EN_WEAK_ADJECTIVE)
🔇 Additional comments (9)
README.md (1)
23-43: Well-structured documentation of current size-calculation approach and future improvements.The new "Known Issues / Future Ideas" section clearly documents the approximate 2% estimation error, proposes a concrete improvement using
du, and thoughtfully addresses the challenges with move operations. This is helpful context for future contributors.emhttp/plugins/dynamix/Browse.page (8)
31-35: LGTM!The switch from
htmlspecialchars_decodetorawurldecodeis appropriate for handling URL-encoded directory paths. Usingjson_encode()withJSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODEcorrectly escapes the path for safe JavaScript injection while maintaining readability.
62-97: LGTM!The
escapeHtml()function uses the standard DOM-based pattern for XSS-safe escaping. TheaddActionWarning()utility cleanly consolidates warning text generation with proper localization support and action-specific messaging for both single and bulk operations.
706-746: LGTM!The integration of
SHOW_POPULARindata-pickfilterand thedfm-target-with-treeclass addition properly enable the new popular destinations feature and tree-associated styling for copy/move dialogs.
785-919: LGTM!The dialog configuration is well-structured with:
- Consistent
ui-corner-allstyling- Proper
opencallback integration for action warnings- Navigation setup correctly gated to copy/move actions (3, 4, 8, 9)
- Clean dialog lifecycle with
close()beforedestroy()
1001-1021: LGTM!The conditional filter logic correctly distinguishes between bulk/directory operations (which need
HIDE_FILES_FILTER) and single file operations. This mirrors the single-action dialog behavior appropriately.
1350-1408: LGTM!The
xlink()rewrite properly implements:
- XSS-safe path display via
escapeHtml()- Mobile-friendly text selection with readonly textarea
- Modern clipboard API with graceful silent fallback
- Terminal integration via cancel button repurposing
Based on learnings, the silent clipboard failure on HTTP connections is intentional to avoid annoying repetitive error messages, with the pre-selected text allowing manual copying.
1415-1416: LGTM!Proper separation of concerns:
escapeHtml()for display text andencodeURIComponent()for URL paths. This correctly handles special characters like&in directory names that were previously displaying as literal&.
400-564: Document-level event listener cleanup is already reliable.The function attaches event listeners to
documentin capture phase (lines 453 and 494), with cleanup tied to thedialogcloseevent. jQuery UI reliably firesdialogclosewheneverdialog('close')is called, and all dialog close paths in the code callclose()beforedestroy(). The current cleanup strategy is sound and will execute on all normal dialog closure paths.Adding cleanup to the existing
closecallback would be defensive but is not necessary.
- Use addActionWarning() in dialog open callback to remove duplication - Fix HTML entity display in breadcrumb and share link Literal ampersands (foo&bar) were displayed as foo&bar - Add global escapeHtml() utility function for consistent HTML escaping
4085575 to
007f8c8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
emhttp/plugins/dynamix/Browse.page (5)
62-67: Clarify the comment about entity preservation.The comment states this function "preserves literal &" but the implementation will actually double-escape entities. If the input contains
&, the output will be&amp;becausetextContenttreats the input as literal text. If this is intentional, clarify the comment to explain the double-escaping behavior.📝 Suggested comment clarification
-// HTML-escape function to preserve literal & and other entities +// HTML-escape function for client-side use (double-escapes existing entities) function escapeHtml(text) {
69-97: Consider adding validation for the action parameter.The function looks up
warningTexts[action]without validating that the action is within the expected range. While the code handles the case whenwarningTextis undefined by not adding anything, it would be clearer to validate the action parameter upfront for debugging purposes.♻️ Optional validation
function addActionWarning(action, isBulk) { + if (typeof action !== 'number' || action < 0) { + console.warn('Invalid action parameter:', action); + return; + } var warningTexts = isBulk ? {
400-564: Good navigation implementation with proper cleanup.The function correctly uses capture-phase event listeners to prevent the file tree from closing, manages state appropriately, and includes proper cleanup on dialog close to prevent memory leaks. The try-catch around tree.show() is good defensive coding.
The function is quite large (~165 lines) and handles multiple concerns (event prevention, popular destinations, input handling, backward navigation, cleanup). While it works correctly, consider extracting some of these concerns into separate helper functions for improved maintainability in future refactoring.
606-635: Consider capping the navigation timeout for deep paths.The timeout calculation
parts.length * FOLDER_EXPAND_DELAY + NAVIGATION_BUFFERcould result in very long timeouts for deeply nested paths (e.g., a 100-level deep path would result in 30+ seconds). Consider adding a maximum timeout cap to prevent UI unresponsiveness with extremely deep paths.♻️ Suggested fix
// Reset flag after navigation completes + var maxTimeout = 10000; // Cap at 10 seconds + var calculatedTimeout = parts.length * FOLDER_EXPAND_DELAY + NAVIGATION_BUFFER; setTimeout(function() { $target.data('isProgrammaticNavigation', false); $target.data('savedInputValue', ''); - }, parts.length * FOLDER_EXPAND_DELAY + NAVIGATION_BUFFER); + }, Math.min(calculatedTimeout, maxTimeout)); }
637-660: Consider adding a recursion depth limit.The recursive function doesn't have a maximum depth check. While the timeout in
navigateFileTreeprovides an indirect limit, adding an explicit depth check would make the code more robust and easier to debug if issues arise with deeply nested paths.♻️ Suggested improvement
-function openFolderRecursive($tree, pickroot, parts, index) { - if (index >= parts.length) return; +function openFolderRecursive($tree, pickroot, parts, index, maxDepth) { + maxDepth = maxDepth || 50; // Default max depth + if (index >= parts.length || index >= maxDepth) return; var pathSoFar = pickroot + '/' + parts.slice(0, index + 1).join('/'); var $folderLink = $tree.find('a[rel="' + pathSoFar + '/"]');And update the call in
navigateFileTree:- openFolderRecursive($tree, pickroot, parts, 0); + openFolderRecursive($tree, pickroot, parts, 0, 50);
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
emhttp/plugins/dynamix/Browse.page
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-07-11T17:24:33.977Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2293
File: emhttp/plugins/dynamix.docker.manager/include/Helpers.php:302-304
Timestamp: 2025-07-11T17:24:33.977Z
Learning: In the Unraid WebGUI Docker manager (emhttp/plugins/dynamix.docker.manager/include/Helpers.php), the xmlSecurity() function call is intentionally commented out to allow users to include < and > characters in their Docker template variables on their own servers. Default templates still explicitly disallow tags, but users can customize templates as needed in their self-hosted environment.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T02:06:47.712Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/nchan/parity_list:150-158
Timestamp: 2025-08-13T02:06:47.712Z
Learning: In the unraid/webgui codebase, the publish() and publish_noDupe() functions in emhttp/plugins/dynamix/include/publish.php automatically handle JSON encoding when arrays are passed to them, eliminating the need for manual json_encode() calls at the call sites.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🔇 Additional comments (10)
emhttp/plugins/dynamix/Browse.page (10)
31-35: LGTM: Proper JSON encoding for JavaScript context.The JSON encoding with
JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODEis appropriate for embedding paths in JavaScript, and the comment clearly explains the rationale. Good use ofvaliddir()for path validation.
396-399: LGTM: Well-documented navigation timing constants.The constants are clearly named with explanatory comments, making the code maintainable.
566-584: LGTM: Clean folder closing implementation.The function correctly handles edge cases with early returns and properly manipulates the DOM to close folders.
586-604: LGTM: Proper tree reset with frame timing.The use of
requestAnimationFrameensures the DOM updates are processed before the simulated click, which is the correct approach for this operation.
706-747: LGTM: Consistent popular destinations integration.The
SHOW_POPULARfilter is correctly applied to all copy/move operations, and the conditionalHIDE_FILES_FILTERfor directory operations (lines 1001-1002, 1014-1015) makes sense to prevent selecting files when a directory destination is required.
785-785: LGTM: Proper dialog initialization with rounded corners and warnings.The
opencallback is the correct place to inject the action warnings after the dialog is rendered, and addingui-corner-allfor rounded corners is consistent with the UI improvements mentioned in the PR objectives.Also applies to: 795-797
911-916: LGTM: Navigation setup for appropriate dialog types.The navigation feature is correctly enabled only for copy/move operations where a destination path is needed, with proper validation that the target element exists.
1083-1090: LGTM: Helpful clarifying comments.The added comments improve readability in the switch statement without changing behavior.
1415-1416: LGTM: Proper escaping prevents XSS in breadcrumbs.The use of
escapeHtml()for display text andencodeURIComponent()for URL components correctly prevents XSS vulnerabilities from directory names while maintaining proper URL encoding.
1350-1408: Enhanced path copying with terminal integration.The implementation properly handles path display, clipboard copying, and terminal integration. The
openTerminal()function is available through the HeadInlineJS.php include and the parameters passed ('ttyd', timestamp-based name, and path) match the function signature correctly. The silent fallback for clipboard errors is appropriate.
- Clarify escapeHtml() comment to explain double-escaping behavior For literal "foo&bar", produces "foo&amp;bar" in HTML which browsers decode back to "foo&bar" for display - Add action parameter validation in addActionWarning() Validates action is a positive number, logs warning if invalid - Add 10-second timeout cap for deep path navigation Prevents UI unresponsiveness with extremely deep paths (100+ levels) - Add recursion depth limit (default 100) to openFolderRecursive() Makes code more robust and easier to debug for edge cases
Remove dfm_htmlspecialchars() from upload filename transmission. HTML-escaping was causing double-encoding: foo&bar.zip became foo&amp;bar.zip on filesystem. Changes: - Remove dfm_htmlspecialchars() when building filePath for upload - Remove dfm_htmlspecialchars() from cleanup file parameter - Add escapeHtml() for upload progress display (HTML context) - Filename is now correctly transmitted via encodeURIComponent/rawurldecode Result: File "foo&bar.zip" now uploads as "foo&bar.zip" on disk, and displays correctly in upload progress.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/Browse.page (1)
460-461: Add defensive cleanup of event listeners in the dialog's close callback.The document-level event listeners (
treeClickHandler,popularClickHandler) are properly cleaned up in thedialogclosehandler, but sincedialog('destroy')does not trigger thedialogcloseevent (onlydialog('close')does), these listeners could leak if code paths destroy the dialog without closing it first. While the current code always callsclosebeforedestroy, this pattern is fragile for future maintenance.Move listener cleanup to the dialog's
closecallback or add additional cleanup logic indestroyto ensure listeners are always removed regardless of the destruction sequence.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
emhttp/plugins/dynamix/Browse.page
🧰 Additional context used
🧠 Learnings (9)
📚 Learning: 2025-12-30T20:28:06.818Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2501
File: emhttp/plugins/dynamix/Browse.page:1282-1339
Timestamp: 2025-12-30T20:28:06.818Z
Learning: In emhttp/plugins/dynamix/Browse.page, the xlink() function's clipboard functionality is intentionally designed to silently fail on HTTP connections without showing warnings. The path text is pre-selected to allow manual copying, which is preferred over showing repetitive error messages that would annoy HTTP users.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-31T00:04:34.204Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-31T00:04:34.204Z
Learning: For the unraid/webgui legacy codebase, ARIA labels and accessibility concerns should not be addressed in individual PRs. These will be handled via a different solution in the future.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T03:13:53.283Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/include/publish.php:28-36
Timestamp: 2025-08-13T03:13:53.283Z
Learning: In the unraid/webgui codebase, PR #2333 by Squidly271 supersedes earlier work that already addressed all legacy publish() calls using the old overloaded syntax. There are no remaining legacy calls that need backward compatibility handling in the publish() function.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-21T00:10:40.789Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2258
File: emhttp/plugins/dynamix/DashStats.page:0-0
Timestamp: 2025-06-21T00:10:40.789Z
Learning: In the Unraid webgui codebase (emhttp/plugins/dynamix), replacing `<i>` elements with `<button>` elements for accessibility would require extensive CSS refactoring due to legacy CSS having direct button styles that would conflict with icon-based toggles.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-06-03T21:27:15.912Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2230
File: emhttp/plugins/dynamix/include/Templates.php:63-74
Timestamp: 2025-06-03T21:27:15.912Z
Learning: In the Unraid WebGUI codebase (emhttp/plugins/dynamix/include/Templates.php), there are known duplicate ID issues in checkbox templates across multiple template instances that the maintainers are aware of but have chosen not to address due to the effort required for legacy code improvements.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-05-28T20:54:31.390Z
Learnt from: zackspear
Repo: unraid/webgui PR: 0
File: :0-0
Timestamp: 2025-05-28T20:54:31.390Z
Learning: In the unraid/webgui repository, the CSS rule `div.title.ud, div#title.ud { margin-top: 0 !important; }` uses `!important` specifically to override CSS that's added by a plugin, which is a necessary approach for ensuring proper title positioning and preventing overlap with tabs.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-09-05T19:26:36.587Z
Learnt from: zackspear
Repo: unraid/webgui PR: 2354
File: emhttp/plugins/dynamix/ShareEdit.page:0-0
Timestamp: 2025-09-05T19:26:36.587Z
Learning: In emhttp/plugins/dynamix/ShareEdit.page, the clone-settings div was moved outside the form element and both are wrapped in a div.relative container to prevent event bubbling issues while maintaining proper positioning.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-07-11T17:24:33.977Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2293
File: emhttp/plugins/dynamix.docker.manager/include/Helpers.php:302-304
Timestamp: 2025-07-11T17:24:33.977Z
Learning: In the Unraid WebGUI Docker manager (emhttp/plugins/dynamix.docker.manager/include/Helpers.php), the xmlSecurity() function call is intentionally commented out to allow users to include < and > characters in their Docker template variables on their own servers. Default templates still explicitly disallow tags, but users can customize templates as needed in their self-hosted environment.
Applied to files:
emhttp/plugins/dynamix/Browse.page
📚 Learning: 2025-08-13T02:06:47.712Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2333
File: emhttp/plugins/dynamix/nchan/parity_list:150-158
Timestamp: 2025-08-13T02:06:47.712Z
Learning: In the unraid/webgui codebase, the publish() and publish_noDupe() functions in emhttp/plugins/dynamix/include/publish.php automatically handle JSON encoding when arrays are passed to them, eliminating the need for manual json_encode() calls at the call sites.
Applied to files:
emhttp/plugins/dynamix/Browse.page
🔇 Additional comments (11)
emhttp/plugins/dynamix/Browse.page (11)
31-35: LGTM - Good separation of encoding contexts.Using
rawurldecode()for the PHP path andjson_encode()with appropriate flags for JavaScript context is the correct approach. The comments clearly explain the encoding decisions.
62-104: LGTM - Safe HTML escaping and well-structured warning system.The DOM-based
escapeHtml()implementation is a reliable pattern. TheaddActionWarning()function correctly validates input and handles the case where an action has no defined warning text by simply not displaying one.
573-611: LGTM - Clean utility functions for tree manipulation.The
closeFolderPath()andresetFileTree()implementations properly handle DOM updates and userequestAnimationFrameappropriately for timing-sensitive operations.
613-670: LGTM - Robust recursive navigation with appropriate safeguards.The navigation functions include sensible limits (10-second timeout cap, maxDepth=100) to prevent runaway operations on deep directory structures. The delay-based recursion properly accounts for DOM update timing.
716-756: LGTM - Consistent integration of popular destinations feature.The
SHOW_POPULARfilter anddfm-target-with-treeclass are consistently applied across copy/move operations for both folders and files.
795-926: LGTM - Dialog handling is well-integrated.The dialog configuration correctly applies styling classes, invokes action warnings, and conditionally enables tree navigation for copy/move operations.
1011-1031: LGTM - Bulk operations correctly apply filter based on content type.The conditional
HIDE_FILES_FILTERfor bulk or directory operations is appropriate, andSHOW_POPULARis consistently applied.
1361-1418: LGTM - Clipboard functionality with appropriate silent fallback.The implementation correctly uses
escapeHtml()for display, plain text for clipboard, and silently handles clipboard failures to allow manual copy. This aligns with the established pattern for HTTP connections. Based on learnings, the silent failure approach is intentional to avoid repetitive error messages.
1425-1426: LGTM - Proper escaping in breadcrumb rendering.The
escapeHtml()function is correctly applied to directory names while the home icon HTML is safely handled as a literal. URL parameters are properly encoded withencodeURIComponent().
316-317: LGTM - Consistent dialog cleanup pattern.The
dialog('close')followed bydialog('destroy')pattern is consistently applied, ensuring proper event triggering (includingdialogclosefor cleanup handlers) before destroying the dialog instance.Also applies to: 321-322
1283-1284: No issues found. Line 1283 correctly sends onlyfile.nameto the 'stop' mode handler, which explicitly usesbasename()to extract the filename for security purposes (preventing path traversal). This is intentional and consistent with the server-side implementation.Likely an incorrect or invalid review comment.
- Add defensive event listener cleanup in dialog close callbacks
- Use global cleanup function to prevent memory leaks
- Only execute cleanup when navigation listeners exist
- Use .closest('li') instead of .parent() for DOM traversal robustness
- Makes code resilient to HTML structure changes in jqueryFileTree
- Fixes ReferenceError when closing dialogs without navigation setup
Addresses code review items:
- Line 460-461: Event listener cleanup fragility
- Line 637-660: DOM traversal robustness
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
Ok, all merge conflicts have been solved, feedback of ai bot has been implemented (if useful) and while doing that, several small bugs have been fixed, too. Ready for merge. |
This PR addresses multiple issues and feature requests:
Browse.pageExample:
Create-Dialog is smaller because it does not have the margin:
Totalduring operationsTERMINALbuttonmoreGET param inOpenTerminal.phpas path parameter/rootas$HOMEdirPopularDestinations.phpwith frequency-based scoring system/boot/config/filemanager.json(will be re-used for future persistent FileManager settings)Example:
filemanager.json:/path/into the target input field, automatically "opens" the visual representation of this directory in the FileTree browsersetupTargetNavigation()functionExample:
filetree-upgrade.mp4
<dt>elements and center next<dd>content next to itAdditional fixes:
Fixes #2500
Dependencies
This PR depends on the following PRs being merged first:
Summary by CodeRabbit
New Features
UI Improvements
Stability
✏️ Tip: You can customize this high-level summary in your review settings.