Skip to content

Commit 8308cbf

Browse files
committed
fix(check_port): Render UI dynamically to fix layout bug
When only one IP version (e.g., IPv6) was enabled, empty HTML elements for the disabled version (IPv4) were still rendered in the DOM and hidden with CSS. This created unwanted extra spacing due to the Flexbox `gap` property, breaking the visual layout. This commit modifies init.js to build the port status UI dynamically. It now checks the configuration received from the backend (use_ipv4, use_ipv6) before creating the corresponding HTML elements. Only the necessary components (icons, text spans, and separator) are added to the DOM, ensuring a correct layout regardless of which IP versions are enabled and resolving the spacing issue.
1 parent 24f8ebf commit 8308cbf

File tree

1 file changed

+69
-51
lines changed

1 file changed

+69
-51
lines changed

plugins/check_port/init.js

Lines changed: 69 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,25 @@ plugin.loadMainCSS();
55
// Cache jQuery elements for performance and readability
66
const a = {};
77

8+
// Flag to track if the UI has been built
9+
plugin.ui_initialized = false;
10+
811
/**
912
* Resets the UI elements to a neutral/unknown state, typically while checking
1013
* @param {boolean} isUpdate - If true, indicates a manual refresh, adding "..." to the title
1114
*/
1215
plugin.resetStatus = function(isUpdate) {
13-
// Reset icons to the "unknown" state (pstatus0) and ensure they are visible for the loading state
14-
a.iconIPv4.removeClass().addClass("icon pstatus0").show();
15-
a.iconIPv6.removeClass().addClass("icon pstatus0").show();
16+
// Exit if the UI hasn't been created yet
17+
if (!plugin.ui_initialized) return;
18+
19+
// Reset icons to the "unknown" state (pstatus0)
20+
if (a.iconIPv4) a.iconIPv4.removeClass().addClass("icon pstatus0").show();
21+
if (a.iconIPv6) a.iconIPv6.removeClass().addClass("icon pstatus0").show();
1622

1723
// Hide IP address text and the separator
18-
a.textIPv4.text("").hide();
19-
a.separator.text("").hide();
20-
a.textIPv6.text("").hide();
24+
if (a.textIPv4) a.textIPv4.text("").hide();
25+
if (a.separator) a.separator.text("").hide();
26+
if (a.textIPv6) a.textIPv6.text("").hide();
2127

2228
// Set a tooltip to indicate that a check is in progress
2329
let title = theUILang.checkingPort || "Checking port status...";
@@ -27,13 +33,6 @@ plugin.resetStatus = function(isUpdate) {
2733
a.pane.prop("title", title);
2834
};
2935

30-
// Initial check when the plugin is first loaded
31-
plugin.init = function() {
32-
plugin.resetStatus(false);
33-
// Request the initial port status from the backend
34-
theWebUI.request("?action=initportcheck", [plugin.getPortStatus, plugin]);
35-
};
36-
3736
// Function to manually trigger an update of the port status
3837
plugin.update = function() {
3938
plugin.resetStatus(true);
@@ -49,15 +48,12 @@ plugin.update = function() {
4948
* @returns {string} The formatted title line for this protocol's status
5049
*/
5150
function updateProtocolStatus(data, proto, getStatusText) {
52-
const isEnabled = data['use_' + proto];
5351
const icon = (proto === 'ipv4') ? a.iconIPv4 : a.iconIPv6;
5452
const textEl = (proto === 'ipv4') ? a.textIPv4 : a.textIPv6;
5553

56-
// Handle the case where the protocol is not enabled in conf.php
57-
if (!isEnabled) {
58-
icon.hide();
59-
textEl.hide();
60-
return ""; // Return an empty title line if not enabled
54+
// If the elements for this protocol don't exist, exit.
55+
if (!icon) {
56+
return "";
6157
}
6258

6359
const status = parseInt(data[proto + '_status']);
@@ -92,6 +88,47 @@ function updateProtocolStatus(data, proto, getStatusText) {
9288
* @param {object} d - The JSON object received from the backend response
9389
*/
9490
plugin.getPortStatus = function(d) {
91+
// On the first run, build the UI dynamically based on the configuration
92+
if (!plugin.ui_initialized) {
93+
// The pane container already exists, just clear it before building the final UI
94+
a.pane.empty();
95+
96+
const container = a.pane; // Use the existing container
97+
98+
if (d.use_ipv4) {
99+
container.append($("<div>").attr("id", "port-icon-ipv4").addClass("icon"));
100+
container.append($("<span>").attr("id", "port-ip-text-ipv4").addClass("d-none d-lg-block port-ip-text-segment"));
101+
}
102+
103+
if (d.use_ipv4 && d.use_ipv6) {
104+
container.append($("<span>").attr("id", "port-ip-separator").addClass("d-none d-lg-block"));
105+
}
106+
107+
if (d.use_ipv6) {
108+
container.append($("<div>").attr("id", "port-icon-ipv6").addClass("icon"));
109+
container.append($("<span>").attr("id", "port-ip-text-ipv6").addClass("d-none d-lg-block port-ip-text-segment"));
110+
}
111+
112+
// Cache the newly created elements
113+
if (d.use_ipv4) {
114+
a.iconIPv4 = $("#port-icon-ipv4");
115+
a.textIPv4 = $("#port-ip-text-ipv4");
116+
}
117+
if (d.use_ipv4 && d.use_ipv6) {
118+
a.separator = $("#port-ip-separator");
119+
}
120+
if (d.use_ipv6) {
121+
a.iconIPv6 = $("#port-icon-ipv6");
122+
a.textIPv6 = $("#port-ip-text-ipv6");
123+
}
124+
125+
// Attach the context menu if permitted
126+
if (plugin.canChangeMenu()) {
127+
a.pane.on("mousedown", plugin.createPortMenu);
128+
}
129+
plugin.ui_initialized = true;
130+
}
131+
95132
// Helper function to get the localized text for a status code
96133
const getStatusText = (statusCode) => theUILang.portStatus[statusCode] || theUILang.portStatus[0] || "Unknown";
97134

@@ -101,12 +138,13 @@ plugin.getPortStatus = function(d) {
101138
updateProtocolStatus(d, 'ipv6', getStatusText)
102139
].filter(line => line); // Filter out empty strings for disabled/unavailable protocols
103140

104-
// Show a separator only if both protocol icons are visible
105-
// The CSS 'gap' property will handle the spacing automatically
106-
if (a.iconIPv4.is(":visible") && a.iconIPv6.is(":visible")) {
107-
a.separator.text("|").show();
108-
} else {
109-
a.separator.text("").hide();
141+
// Show a separator only if it exists and both protocol icons are visible
142+
if (a.separator) {
143+
if (a.iconIPv4.is(":visible") && a.iconIPv6.is(":visible")) {
144+
a.separator.text("|").show();
145+
} else {
146+
a.separator.text("").hide();
147+
}
110148
}
111149

112150
// Set the combined tooltip for the entire status pane
@@ -139,36 +177,16 @@ plugin.createPortMenu = function(e) {
139177
};
140178

141179
plugin.onLangLoaded = function() {
142-
// Create status bar elements in a more readable way
143-
const container = $("<div>").addClass("port-status-container");
144-
145-
const ipv4Icon = $("<div>").attr("id", "port-icon-ipv4").addClass("icon");
146-
const ipv4Text = $("<span>").attr("id", "port-ip-text-ipv4").addClass("d-none d-lg-block port-ip-text-segment");
147-
const separator = $("<span>").attr("id", "port-ip-separator").addClass("d-none d-lg-block");
148-
const ipv6Icon = $("<div>").attr("id", "port-icon-ipv6").addClass("icon");
149-
const ipv6Text = $("<span>").attr("id", "port-ip-text-ipv6").addClass("d-none d-lg-block port-ip-text-segment");
150-
151-
// Assemble the elements into the container
152-
container.append(ipv4Icon, ipv4Text, separator, ipv6Icon, ipv6Text);
180+
// Create a temporary loading state immediately
181+
const container = $("<div>").addClass("port-status-container")
182+
.append($("<div>").addClass("icon pstatus0")); // Add a single "unknown" icon as a placeholder
153183

154-
// Add the newly created pane to the ruTorrent status bar
155184
plugin.addPaneToStatusbar("port-pane", container, -1, true);
156-
157-
// Now that the pane is in the DOM, cache all the jQuery elements for future use
158185
a.pane = $("#port-pane");
159-
a.iconIPv4 = $("#port-icon-ipv4");
160-
a.textIPv4 = $("#port-ip-text-ipv4");
161-
a.separator = $("#port-ip-separator");
162-
a.iconIPv6 = $("#port-icon-ipv6");
163-
a.textIPv6 = $("#port-ip-text-ipv6");
164-
165-
// If the user has permissions, attach the right-click context menu
166-
if (plugin.canChangeMenu()) {
167-
a.pane.on("mousedown", plugin.createPortMenu);
168-
}
186+
a.pane.prop("title", theUILang.checkingPort || "Checking port status...");
169187

170-
// Trigger the initial port check
171-
plugin.init();
188+
// Trigger the initial port check to get the configuration and build the final UI
189+
theWebUI.request("?action=initportcheck", [plugin.getPortStatus, plugin]);
172190
};
173191

174192
// This function is called when the plugin is removed/unloaded

0 commit comments

Comments
 (0)