@@ -5,19 +5,25 @@ plugin.loadMainCSS();
55// Cache jQuery elements for performance and readability
66const 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 */
1215plugin . 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
3837plugin . 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 */
5150function 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 */
9490plugin . 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
141179plugin . 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