Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions nym-vpn-app/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions nym-vpn-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
},
"dependencies": {
"@base-ui-components/react": "^1.0.0-beta.3",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@headlessui/react": "^2.1.2",
"@lottiefiles/dotlottie-react": "^0.17.0",
"@radix-ui/react-accordion": "^1.2.3",
Expand Down
28 changes: 28 additions & 0 deletions nym-vpn-app/src-tauri/src/commands/tunnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{
tunnel::{ConnectingState, TunnelState},
},
};
use std::net::IpAddr;
use tauri::{Manager, State};
use tracing::{debug, info, instrument, warn};

Expand Down Expand Up @@ -153,3 +154,30 @@ pub async fn set_allow_lan(vpnd: State<'_, VpndClient>, enabled: bool) -> Result
vpnd.set_allow_lan(enabled).await?;
Ok(())
}

#[instrument(skip(vpnd))]
#[tauri::command]
pub async fn get_default_dns(vpnd: State<'_, VpndClient>) -> Result<Vec<IpAddr>, BackendError> {
let dns = vpnd.get_default_dns().await?;
Ok(dns)
}

#[instrument(skip(vpnd))]
#[tauri::command]
pub async fn set_custom_dns_enabled(
vpnd: State<'_, VpndClient>,
enabled: bool,
) -> Result<(), BackendError> {
vpnd.set_custom_dns_enabled(enabled).await?;
Ok(())
}

#[instrument(skip(vpnd))]
#[tauri::command]
pub async fn set_custom_dns(
vpnd: State<'_, VpndClient>,
dns: Vec<IpAddr>,
) -> Result<(), BackendError> {
vpnd.set_custom_dns(dns).await?;
Ok(())
}
3 changes: 3 additions & 0 deletions nym-vpn-app/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ async fn main() -> Result<()> {
tunnel::disconnect,
tunnel::set_node,
tunnel::set_quic,
tunnel::get_default_dns,
tunnel::set_custom_dns,
tunnel::set_custom_dns_enabled,
tunnel::set_no_ipv6,
tunnel::set_allow_lan,
cmd_db::db_set,
Expand Down
41 changes: 41 additions & 0 deletions nym-vpn-app/src-tauri/src/vpnd/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use nym_vpn_proto::rpc_client::RpcClient;
use once_cell::sync::Lazy;
use std::{
env::consts::{ARCH, OS},
net::IpAddr,
path::PathBuf,
sync::Mutex,
};
Expand Down Expand Up @@ -772,6 +773,46 @@ impl VpndClient {
Ok(())
}

#[instrument(skip_all)]
pub async fn get_default_dns(&self) -> Result<Vec<IpAddr>, VpndError> {
let mut vpnd = self.vpnd().await?;

let dns = vpnd.get_default_dns().await.map_err(|e| {
error!("failed to get default DNS: {}", e);
VpndError::RpcClient(e)
})?;

Ok(dns)
}

#[instrument(skip_all)]
pub async fn set_custom_dns_enabled(&self, enabled: bool) -> Result<(), VpndError> {
let mut vpnd = self.vpnd().await?;

vpnd.set_enable_custom_dns(enabled)
.await
.map_err(VpndError::RpcClient)
.inspect_err(|e| {
error!("failed to set custom DNS enabled: {}", e);
})?;

Ok(())
}

#[instrument(skip_all)]
pub async fn set_custom_dns(&self, dns: Vec<IpAddr>) -> Result<(), VpndError> {
let mut vpnd = self.vpnd().await?;

vpnd.set_custom_dns(dns)
.await
.map_err(VpndError::RpcClient)
.inspect_err(|e| {
error!("failed to set custom DNS: {}", e);
})?;

Ok(())
}

pub fn reset_log_flag() {
let mut logged = VPND_DOWN_LOGGED.lock().unwrap();
*logged = false;
Expand Down
2 changes: 2 additions & 0 deletions nym-vpn-app/src-tauri/src/vpnd/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct VpndConfig {
pub entry_node: Node,
pub exit_node: Node,
pub custom_dns: Option<Vec<IpAddr>>,
pub enable_custom_dns: bool,
pub allow_lan: bool,
pub disable_ipv6: bool,
pub vpn_mode: VpnMode,
Expand All @@ -38,6 +39,7 @@ impl VpndConfig {
entry_node: config.entry_point.into(),
exit_node: config.exit_point.try_into()?,
custom_dns: Some(config.custom_dns),
enable_custom_dns: config.enable_custom_dns,
allow_lan: config.allow_lan,
disable_ipv6: config.disable_ipv6,
vpn_mode,
Expand Down
9 changes: 6 additions & 3 deletions nym-vpn-app/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
MainStateProvider,
NodeListStateProvider,
Socks5Provider,
TopBarProvider,
} from './contexts';
import { useLang } from './hooks';
import { LngTag } from './i18n';
Expand Down Expand Up @@ -74,9 +75,11 @@ function App({ init }: { init: InitState }) {
<Socks5Provider>
<ThemeSetter>
<DialogProvider>
<Suspense fallback={<RouteLoading />}>
<RouterProvider router={router} />
</Suspense>
<TopBarProvider>
<Suspense fallback={<RouteLoading />}>
<RouterProvider router={router} />
</Suspense>
</TopBarProvider>
</DialogProvider>
</ThemeSetter>
</Socks5Provider>
Expand Down
3 changes: 3 additions & 0 deletions nym-vpn-app/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ export const ResidentialIpServersUrl =
'https://support.nym.com/hc/en-us/articles/35279486714641-Why-can-t-I-access-streaming-services-while-using-NymVPN';
export const QuicSupportArticleUrl =
'https://support.nym.com/hc/en-us/articles/39648047741457-QUIC-transport-mode';
export const LocationAccuracyLink =
'https://support.nym.com/hc/en-us/articles/26448676449297-How-is-server-location-determined-by-NymVPN';
export const CustomDnsHelpUrl = 'https://nym.com/features/custom-dns';
1 change: 1 addition & 0 deletions nym-vpn-app/src/contexts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './node-list';
export * from './node-list-state';
export * from './gateways';
export * from './socks5';
export * from './topbar';
2 changes: 2 additions & 0 deletions nym-vpn-app/src/contexts/main/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ function MainStateProvider({ children, init }: Props) {
quic: init.quic,
ipv6Support: !init.noIpv6,
allowLan: init.allowLan,
customDnsEnabled: init.customDnsEnabled,
customDns: init.customDns,
});

const { push } = useInAppNotify();
Expand Down
24 changes: 22 additions & 2 deletions nym-vpn-app/src/contexts/main/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ export type StateAction =
| { type: 'set-backend-flags'; flags: FeatureFlags }
| { type: 'set-quic'; enabled: boolean }
| { type: 'set-domain-fronting'; enabled: boolean }
| { type: 'set-streaming-optimized-label-seen'; seen: boolean };
| { type: 'set-streaming-optimized-label-seen'; seen: boolean }
| { type: 'set-custom-dns-enabled'; enabled: boolean }
| { type: 'set-custom-dns'; dns: string[] }
| { type: 'set-default-dns'; dns: string[] };

export const initialState: AppState = {
initialized: false,
Expand Down Expand Up @@ -115,6 +118,9 @@ export const initialState: AppState = {
zknymCredential: false,
},
streamingOptimizedLabelSeen: false,
customDnsEnabled: false,
customDns: [],
defaultDns: [],
};

export function reducer(state: AppState, action: StateAction): AppState {
Expand Down Expand Up @@ -380,7 +386,21 @@ export function reducer(state: AppState, action: StateAction): AppState {
...state,
domainFronting: action.enabled,
};

case 'set-custom-dns-enabled':
return {
...state,
customDnsEnabled: action.enabled,
};
case 'set-custom-dns':
return {
...state,
customDns: action.dns,
};
case 'set-default-dns':
return {
...state,
defaultDns: action.dns,
};
case 'reset':
return initialState;
}
Expand Down
23 changes: 23 additions & 0 deletions nym-vpn-app/src/contexts/topbar/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createContext, useContext } from 'react';

export type TopBarContextType = {
// Custom handler that overrides the default left nav behavior
readonly customLeftNavHandler: (() => void) | null;
// Set a custom handler for the left navigation button
// Call with null to clear the custom handler
readonly setCustomLeftNavHandler: (handler: (() => void) | null) => void;
};

const init: TopBarContextType = {
customLeftNavHandler: null,
setCustomLeftNavHandler: () => {
/* SCARECROW */
},
};

export const TopBarContext = createContext<TopBarContextType>(init);

// Access the TopBar context
export const useTopBar = () => {
return useContext(TopBarContext);
};
3 changes: 3 additions & 0 deletions nym-vpn-app/src/contexts/topbar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as TopBarProvider } from './provider';
export { useTopBar } from './context';
export * from './provider';
33 changes: 33 additions & 0 deletions nym-vpn-app/src/contexts/topbar/provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useCallback, useMemo, useState } from 'react';
import { TopBarContext } from './context';

export type TopBarProviderProps = {
children: React.ReactNode;
};

function TopBarProvider({ children }: TopBarProviderProps) {
const [customLeftNavHandler, setCustomLeftNavHandlerState] = useState<
(() => void) | null
>(null);

const setCustomLeftNavHandler = useCallback(
(handler: (() => void) | null) => {
setCustomLeftNavHandlerState(() => handler);
},
[],
);

const ctx = useMemo(
() => ({
customLeftNavHandler,
setCustomLeftNavHandler,
}),
[customLeftNavHandler, setCustomLeftNavHandler],
);

return (
<TopBarContext.Provider value={ctx}>{children}</TopBarContext.Provider>
);
}

export default TopBarProvider;
Loading