@@ -31,6 +31,12 @@ export default {
3131 rigModels: [] as RigModel [],
3232 loadingModels: false ,
3333 wsjtxEnabled: false ,
34+ firewallStatus: {
35+ isConfiguring: false ,
36+ success: false ,
37+ error: null as string | null ,
38+ userCancelled: false ,
39+ },
3440 connectionForm: {
3541 host: ' localhost' ,
3642 port: 4532 ,
@@ -87,6 +93,18 @@ export default {
8793 hasSuggestions() {
8894 return this .rigStore .connectionSuggestions && this .rigStore .connectionSuggestions .length > 0 ;
8995 },
96+ hasFirewallSuggestion() {
97+ if (! this .hasSuggestions ) return false ;
98+ return this .rigStore .connectionSuggestions .some (suggestion =>
99+ suggestion .toLowerCase ().includes (' firewall' )
100+ );
101+ },
102+ showFirewallAction() {
103+ return (
104+ ! this .rigStore .isConnected &&
105+ (this .hasFirewallSuggestion || this .rigStore .diagnostics ?.firewallOk === false )
106+ );
107+ },
90108 firstSuggestion() {
91109 if (this .hasSuggestions ) {
92110 return this .rigStore .connectionSuggestions [0 ];
@@ -443,6 +461,28 @@ export default {
443461 console .log (' Diagnostics result:' , diagnostics );
444462 }
445463 },
464+ async addFirewallExceptions() {
465+ if (this .firewallStatus .isConfiguring ) return ;
466+ this .firewallStatus .isConfiguring = true ;
467+ this .firewallStatus .success = false ;
468+ this .firewallStatus .error = null ;
469+ this .firewallStatus .userCancelled = false ;
470+
471+ try {
472+ const result = await window .electronAPI .addFirewallExceptions ();
473+ if (result .success ) {
474+ this .firewallStatus .success = true ;
475+ } else if (result .userCancelled ) {
476+ this .firewallStatus .userCancelled = true ;
477+ } else {
478+ this .firewallStatus .error = result .error || ' Unknown error occurred' ;
479+ }
480+ } catch (error ) {
481+ this .firewallStatus .error = error instanceof Error ? error .message : ' Unknown error occurred' ;
482+ } finally {
483+ this .firewallStatus .isConfiguring = false ;
484+ }
485+ },
446486 },
447487
448488 beforeUnmount() {
@@ -471,6 +511,24 @@ export default {
471511 <div v-if =" hasSuggestions && !rigStore.isConnected" class =" suggestion-message" >
472512 {{ firstSuggestion }}
473513 </div >
514+ <div v-if =" showFirewallAction" class =" firewall-action" >
515+ <button
516+ class =" firewall-btn"
517+ @click =" addFirewallExceptions"
518+ :disabled =" firewallStatus.isConfiguring"
519+ >
520+ {{ firewallStatus.isConfiguring ? 'Adding...' : 'Add Firewall Exception' }}
521+ </button >
522+ <div v-if =" firewallStatus.success" class =" success-message" >
523+ Firewall exceptions added successfully.
524+ </div >
525+ <div v-else-if =" firewallStatus.userCancelled" class =" warning-message" >
526+ Firewall configuration was cancelled.
527+ </div >
528+ <div v-else-if =" firewallStatus.error" class =" error-message" >
529+ Firewall configuration failed: {{ firewallStatus.error }}
530+ </div >
531+ </div >
474532 <!-- Diagnostics link when disconnected or error -->
475533 <div v-if =" !rigStore.isConnected && !wsjtxEnabled" class =" diagnostics-link" >
476534 <button
@@ -777,6 +835,43 @@ export default {
777835 border : 1px solid rgba (255 , 193 , 7 , 0.3 );
778836}
779837
838+ .firewall-action {
839+ margin-top : 0.35rem ;
840+ }
841+
842+ .firewall-btn {
843+ background : #ff9800 ;
844+ color : #1a1a1a ;
845+ border : none ;
846+ padding : 0.2rem 0.5rem ;
847+ border-radius : 3px ;
848+ font-size : 0.7rem ;
849+ font-weight : 600 ;
850+ cursor : pointer ;
851+ transition : background 0.2s ease ;
852+ }
853+
854+ .firewall-btn :hover:not (:disabled ) {
855+ background : #ffb347 ;
856+ }
857+
858+ .firewall-btn :disabled {
859+ opacity : 0.6 ;
860+ cursor : not-allowed ;
861+ }
862+
863+ .success-message {
864+ color : #4caf50 ;
865+ font-size : 0.7rem ;
866+ margin-top : 0.25rem ;
867+ }
868+
869+ .warning-message {
870+ color : #ffc107 ;
871+ font-size : 0.7rem ;
872+ margin-top : 0.25rem ;
873+ }
874+
780875.diagnostics-link {
781876 margin-top : 0.3rem ;
782877}
0 commit comments