1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
import * as Uebersicht from "uebersicht";
import * as DataWidget from "./data-widget.jsx";
import * as DataWidgetLoader from "./data-widget-loader.jsx";
import * as Icons from "../icons/icons.jsx";
import useWidgetRefresh from "../../hooks/use-widget-refresh";
import useServerSocket from "../../hooks/use-server-socket";
import { useSimpleBarContext } from "../simple-bar-context.jsx";
import * as Utils from "../../utils";
export { viscosityVPNStyles as styles } from "../../styles/components/data/viscosity-vpn";
const { React } = Uebersicht;
const DEFAULT_REFRESH_FREQUENCY = 8000;
/**
* Viscosity VPN Widget component.
* @returns {JSX.Element|null} The Viscosity VPN widget.
*/
export const Widget = React.memo(() => {
const { displayIndex, settings, pushMissive } = useSimpleBarContext();
const { widgets, vpnWidgetOptions } = settings;
const { vpnWidget } = widgets;
const {
refreshFrequency,
vpnConnectionName,
vpnShowConnectionName,
showOnDisplay,
showIcon,
} = vpnWidgetOptions;
// Determine the refresh frequency for the widget
const refresh = React.useMemo(
() =>
Utils.getRefreshFrequency(refreshFrequency, DEFAULT_REFRESH_FREQUENCY),
[refreshFrequency],
);
// Determine if the widget should be visible
const visible =
Utils.isVisibleOnDisplay(displayIndex, showOnDisplay) && vpnWidget;
const [state, setState] = React.useState();
const [loading, setLoading] = React.useState(visible);
const [isViscosityActive, setIsViscosityActive] = React.useState(false);
/**
* Reset the widget state.
*/
const resetWidget = () => {
setState(undefined);
setLoading(false);
setIsViscosityActive(false);
};
/**
* Fetch the current VPN status.
*/
const getVPN = React.useCallback(async () => {
if (!visible) return;
const isRunning = await Utils.cachedRun(
`pgrep -xq 'Viscosity' && echo "true" || echo "false"`,
refresh,
);
if (Utils.cleanupOutput(isRunning) === "false") {
setLoading(false);
setIsViscosityActive(false);
return;
}
const status = await Utils.cachedRun(
`osascript -e "tell application \\"Viscosity\\" to return state of the first connection where name is equal to \\"${vpnConnectionName}\\"" 2>/dev/null`,
refresh,
);
if (!status.length) return;
setState({ status: Utils.cleanupOutput(status) });
setIsViscosityActive(true);
setLoading(false);
}, [visible, vpnConnectionName, refresh]);
// Use server socket to listen for VPN status updates
useServerSocket("viscosity-vpn", visible, getVPN, resetWidget, setLoading);
// Refresh the widget at the specified interval
useWidgetRefresh(visible, getVPN, refresh);
if (loading) return <DataWidgetLoader.Widget className="viscosity-vpn" />;
if (!state || !vpnConnectionName.length || !isViscosityActive) return null;
const { status } = state;
const isConnected = status === "Connected";
const classes = Utils.classNames("viscosity-vpn", {
"viscosity-vpn--disconnected": !isConnected,
});
const Icon = isConnected ? Icons.VPN : Icons.VPNOff;
/**
* Handle click event to toggle VPN connection.
* @param {Event} e - The click event.
*/
const clicked = (e) => {
Utils.clickEffect(e);
toggleVPN(isConnected, vpnConnectionName, pushMissive);
setTimeout(getVPN, refreshFrequency / 2);
};
return (
<DataWidget.Widget
classes={classes}
Icon={showIcon ? Icon : null}
onClick={clicked}
>
{vpnShowConnectionName ? vpnConnectionName : status}
</DataWidget.Widget>
);
});
Widget.displayName = "ViscosityVPN";
/**
* Toggle the VPN connection.
* @param {boolean} isConnected - Whether the VPN is currently connected.
* @param {string} vpnConnectionName - The name of the VPN connection.
* @param {function} pushMissive - Function to push notifications.
*/
function toggleVPN(isConnected, vpnConnectionName, pushMissive) {
if (isConnected) {
Uebersicht.run(
`osascript -e 'tell application "Viscosity" to disconnect "${vpnConnectionName}"'`,
);
Utils.notification(
`Disabling Viscosity ${vpnConnectionName} network...`,
pushMissive,
);
} else {
Uebersicht.run(
`osascript -e 'tell application "Viscosity" to connect "${vpnConnectionName}"'`,
);
Utils.notification(
`Enabling Viscosity ${vpnConnectionName} network...`,
pushMissive,
);
}
}
|