Skip to content

Commit

Permalink
feat(tauri): add dev menu (#1871)
Browse files Browse the repository at this point in the history
* add a dev menu

* update workflows
  • Loading branch information
doums authored Jan 9, 2025
1 parent df5165b commit 59cd3a4
Show file tree
Hide file tree
Showing 27 changed files with 223 additions and 143 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-nym-vpn-app-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ jobs:
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
APP_SENTRY_DSN: ${{ secrets.DESKTOP_JS_SENTRY_DSN }}
# RUSTFLAGS: "-L ${{ env.WG_GO_LIB_PATH }}"
NETWORK_ENV_SELECT: ${{ inputs.dev_mode == true }}
DEV_MODE: ${{ inputs.dev_mode == true }}
run: |
if [ "${{ env.CARGO_TARGET }}" = "release" ]; then
npm run tauri build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-nym-vpn-app-windows-ev-sign.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ jobs:
RUSTFLAGS: "-L ${{ env.TAURI_SRC }}/x86_64-pc-windows-msvc -L ${{ env.TAURI_SRC }} -Clink-args=/LIBPATH:${{ env.TAURI_SRC }}/x64-${{ env.CPP_BUILD_MODES }}"
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_SIGNING_PFX_BASE64 }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_SIGNING_PFX_PASSWORD }}
NETWORK_ENV_SELECT: ${{ inputs.dev_mode == true }}
DEV_MODE: ${{ inputs.dev_mode == true }}
run: |
if [ "${{ env.CARGO_TARGET }}" = "release" ]; then
npm run tauri build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build-nym-vpn-app-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ jobs:
RUSTFLAGS: "-L ${{ env.TAURI_SRC }}/x86_64-pc-windows-msvc -L ${{ env.TAURI_SRC }} -Clink-args=/LIBPATH:${{ env.TAURI_SRC }}/x64-${{ env.CPP_BUILD_MODES }}"
WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_SIGNING_PFX_BASE64 }}
WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_SIGNING_PFX_PASSWORD }}
NETWORK_ENV_SELECT: ${{ inputs.dev_mode == true }}
DEV_MODE: ${{ inputs.dev_mode == true }}
run: |
if [ "${{ env.CARGO_TARGET }}" = "release" ]; then
npm run tauri build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-nym-vpn-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
type: boolean
default: false
dev_mode:
description: "dev build (enable env selector)"
description: "Enable dev mode (in-app dev menu)"
required: true
type: boolean
default: false
Expand Down
4 changes: 2 additions & 2 deletions nym-vpn-app/src-tauri/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ pub struct Cli {
#[arg(short = 's', long)]
pub nosplash: bool,

/// Enable zknyms credentials mode
// Run in 'dev' mode
#[arg(long, hide = true)]
pub credentials_mode: bool,
pub dev_mode: bool,

#[command(subcommand)]
pub command: Option<Commands>,
Expand Down
2 changes: 2 additions & 0 deletions nym-vpn-app/src-tauri/src/commands/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub async fn connect(
.dns_server
.clone()
.map(|ip| nym_vpn_proto::Dns { ip });
let credentials_mode = app_state.credentials_mode;
// release the lock
drop(app_state);

Expand Down Expand Up @@ -146,6 +147,7 @@ pub async fn connect(
entry_node,
exit_node,
two_hop_mod,
credentials_mode,
use_netstack_wireguard,
dns,
)
Expand Down
6 changes: 3 additions & 3 deletions nym-vpn-app/src-tauri/src/commands/daemon.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::env::NETWORK_ENV_SELECT;
use crate::env::DEV_MODE;
use crate::error::BackendError;
use crate::grpc::client::{FeatureFlags, GrpcClient, SystemMessage, VpndStatus};
use crate::states::SharedAppState;
Expand Down Expand Up @@ -41,8 +41,8 @@ pub async fn set_network(
grpc_client: State<'_, GrpcClient>,
network: NetworkEnv,
) -> Result<(), BackendError> {
if !*NETWORK_ENV_SELECT {
warn!("network env selector is disabled");
if !*DEV_MODE {
warn!("not in dev mode");
return Err(BackendError::internal("nope", None));
}
grpc_client
Expand Down
27 changes: 27 additions & 0 deletions nym-vpn-app/src-tauri/src/commands/dev.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::env::DEV_MODE;
use crate::error::BackendError;
use crate::states::SharedAppState;
use tauri::State;
use tracing::{instrument, warn};

#[instrument(skip(state))]
#[tauri::command]
pub async fn get_credentials_mode(state: State<'_, SharedAppState>) -> Result<bool, BackendError> {
let state = state.lock().await;
Ok(state.credentials_mode)
}

#[instrument(skip(state))]
#[tauri::command]
pub async fn set_credentials_mode(
state: State<'_, SharedAppState>,
enabled: bool,
) -> Result<(), BackendError> {
if !*DEV_MODE {
warn!("not in dev mode");
return Err(BackendError::internal("nope", None));
}
let mut state = state.lock().await;
state.credentials_mode = enabled;
Ok(())
}
6 changes: 3 additions & 3 deletions nym-vpn-app/src-tauri/src/commands/env.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::env::NETWORK_ENV_SELECT;
use crate::env::DEV_MODE;
use serde::Serialize;
use tracing::instrument;
use ts_rs::TS;
Expand All @@ -7,13 +7,13 @@ use ts_rs::TS;
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[ts(export)]
pub struct Env {
network_env_select: bool,
dev_mode: bool,
}

#[instrument(skip_all)]
#[tauri::command]
pub async fn env() -> Env {
Env {
network_env_select: *NETWORK_ENV_SELECT,
dev_mode: *DEV_MODE,
}
}
1 change: 1 addition & 0 deletions nym-vpn-app/src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod connection;
pub mod country;
pub mod daemon;
pub mod db;
pub mod dev;
pub mod env;
pub mod fs;
pub mod log;
Expand Down
8 changes: 4 additions & 4 deletions nym-vpn-app/src-tauri/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use once_cell::sync::Lazy;
use std::env;

/// SemVer version requirement for daemon compatibility
// set at compile time
// comptime
pub const VPND_COMPAT_REQ: Option<&str> = option_env!("VPND_COMPAT_REQ");

// set at compile time
pub static NETWORK_ENV_SELECT: Lazy<bool> = Lazy::new(|| {
option_env!("NETWORK_ENV_SELECT")
// comptime
pub static DEV_MODE: Lazy<bool> = Lazy::new(|| {
option_env!("DEV_MODE")
.map(|v| v == "1" || v.to_lowercase() == "true")
.unwrap_or(false)
});
Expand Down
9 changes: 4 additions & 5 deletions nym-vpn-app/src-tauri/src/grpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::env::VPND_COMPAT_REQ;
use crate::error::BackendError;
use crate::fs::config::AppConfig;
use crate::states::app::ConnectionState;
use crate::{env, vpn_status};
use crate::vpn_status;
use crate::{events::AppHandleEventEmitter, states::SharedAppState};

const VPND_SERVICE: &str = "nym.vpn.NymVpnd";
Expand All @@ -59,7 +59,6 @@ pub struct GrpcClient {
transport: Transport,
pkg_info: PackageInfo,
user_agent: UserAgent,
credentials_mode: bool,
}

impl GrpcClient {
Expand All @@ -69,7 +68,6 @@ impl GrpcClient {
transport: Transport::from((config, cli)),
pkg_info: pkg.clone(),
user_agent: GrpcClient::user_agent(pkg, None),
credentials_mode: cli.credentials_mode || env::is_truthy("ENABLE_CREDENTIALS_MODE"),
};
match &client.transport {
Transport::Http(endpoint) => {
Expand Down Expand Up @@ -348,12 +346,13 @@ impl GrpcClient {
entry_node: EntryNode,
exit_node: ExitNode,
two_hop_mod: bool,
credentials_mode: bool,
netstack: bool,
dns: Option<Dns>,
) -> Result<(), VpndError> {
let mut vpnd = self.vpnd().await?;

if self.credentials_mode {
if credentials_mode {
info!("credentials mode enabled");
}
let request = Request::new(ConnectRequest {
Expand All @@ -364,7 +363,7 @@ impl GrpcClient {
netstack,
disable_poisson_rate: false,
disable_background_cover_traffic: false,
enable_credentials_mode: self.credentials_mode,
enable_credentials_mode: credentials_mode,
dns,
user_agent: Some(self.user_agent.clone()),
min_mixnode_performance: None,
Expand Down
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 @@ -19,6 +19,7 @@ use clap::Parser;
use commands::country as cmd_country;
use commands::daemon as cmd_daemon;
use commands::db as cmd_db;
use commands::dev as cmd_dev;
use commands::env as cmd_env;
use commands::fs as cmd_fs;
use commands::log as cmd_log;
Expand Down Expand Up @@ -222,6 +223,8 @@ async fn main() -> Result<()> {
connection::connect,
connection::disconnect,
connection::get_connection_start_time,
cmd_dev::get_credentials_mode,
cmd_dev::set_credentials_mode,
cmd_db::db_set,
cmd_db::db_get,
cmd_db::db_flush,
Expand Down
2 changes: 2 additions & 0 deletions nym-vpn-app/src-tauri/src/states/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ pub struct AppState {
pub vpn_mode: VpnMode,
pub connection_start_time: Option<OffsetDateTime>,
pub dns_server: Option<String>,
pub credentials_mode: bool,
}

impl AppState {
Expand All @@ -61,6 +62,7 @@ impl AppState {
AppState {
vpn_mode,
dns_server,
credentials_mode: cli.dev_mode,
..Default::default()
}
}
Expand Down
2 changes: 1 addition & 1 deletion nym-vpn-app/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
},
"linux": {
"deb": {
"depends": ["nym-vpnd (>= 1.1.0~beta.2)"],
"depends": ["nym-vpnd (>= 1.2.0~dev)"],
"conflicts": ["nymvpn-x"],
"desktopTemplate": "./bundle/deb/main.desktop"
}
Expand Down
2 changes: 1 addition & 1 deletion nym-vpn-app/src/dev/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export function mockTauriIPC() {
if (cmd === 'env') {
return new Promise((resolve) =>
resolve({
NETWORK_ENV_SELECT: true,
DEV_MODE: true,
}),
);
}
Expand Down
6 changes: 3 additions & 3 deletions nym-vpn-app/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ async function setSplashTheme(window: WebviewWindow) {
}

const env = await invoke<Record<string, unknown>>('env');
if (env.NETWORK_ENV_SELECT === true) {
console.info('network env selector enabled');
S_STATE.networkEnvSelect = true;
if (env.DEV_MODE === true) {
console.info('dev mode enabled');
S_STATE.devMode = true;
}

// check for unrecoverable errors
Expand Down
7 changes: 7 additions & 0 deletions nym-vpn-app/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import * as Sentry from '@sentry/react';
import {
Appearance,
AppearanceRouteIndex,
Dev,
Display,
Error,
Lang,
Expand Down Expand Up @@ -36,6 +37,7 @@ export const routes = {
licensesRust: '/settings/legal/licenses-rust',
licensesJs: '/settings/legal/licenses-js',
licenseDetails: '/settings/legal/license-details',
dev: '/settings/dev',
entryNodeLocation: '/entry-node-location',
exitNodeLocation: '/exit-node-location',
hideout: '/hideout',
Expand Down Expand Up @@ -72,6 +74,11 @@ const router = createRouterFn([
errorElement: <Error />,
index: true,
},
{
path: routes.dev,
element: <Dev />,
errorElement: <Error />,
},
{
path: routes.appearance,
element: <AppearanceRouteIndex />,
Expand Down
43 changes: 43 additions & 0 deletions nym-vpn-app/src/screens/settings/dev/Dev.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useEffect, useState } from 'react';
import { invoke } from '@tauri-apps/api/core';
import { PageAnim, SettingsMenuCard, Switch } from '../../../ui';
import { useMainState } from '../../../contexts';
import NetworkEnvSelect from './NetworkEnvSelect';

function Dev() {
const [credentialsMode, setCredentialsMode] = useState(false);

const { daemonStatus, networkEnv } = useMainState();

useEffect(() => {
const getCredentialsMode = async () => {
const enabled = await invoke<boolean>('get_credentials_mode');
console.log('credentials mode:', enabled);
setCredentialsMode(enabled);
};
getCredentialsMode();
}, []);

const credentialsModeChanged = (enabled: boolean) => {
invoke('set_credentials_mode', { enabled }).then(() => {
setCredentialsMode(enabled);
});
};

return (
<PageAnim className="h-full flex flex-col py-6 gap-6">
<SettingsMenuCard
title={'CREDENTIALS_MODE'}
onClick={() => credentialsModeChanged(!credentialsMode)}
trailingComponent={
<Switch checked={credentialsMode} onChange={credentialsModeChanged} />
}
/>
{daemonStatus !== 'NotOk' && networkEnv && (
<NetworkEnvSelect current={networkEnv} />
)}
</PageAnim>
);
}

export default Dev;
Loading

0 comments on commit 59cd3a4

Please sign in to comment.