From c5f7d066b09122f4b52ecdf3a2fae0fe760eeafe Mon Sep 17 00:00:00 2001 From: Pierre Dommerc Date: Wed, 19 Jul 2023 15:56:00 +0200 Subject: [PATCH] refactor(nc-desktop): add privacy level user settings (#3664) --- .../workflows/nym-connect-s-publish-macos.yml | 104 ------------------ .../nym-connect-s-publish-ubuntu.yml | 85 -------------- .../nym-connect-s-publish-windows10.yml | 104 ------------------ nym-connect/desktop/Cargo.lock | 47 ++++++-- nym-connect/desktop/src-tauri/Cargo.toml | 2 +- nym-connect/desktop/src-tauri/src/build.rs | 7 -- .../desktop/src-tauri/src/config/mod.rs | 4 + .../desktop/src-tauri/src/config/user_data.rs | 67 +++++++++++ nym-connect/desktop/src-tauri/src/error.rs | 2 + nym-connect/desktop/src-tauri/src/main.rs | 21 ++-- .../src-tauri/src/operations/common.rs | 29 +++++ .../src/operations/connection/connect.rs | 1 + .../src/operations/connection/status.rs | 7 +- .../src-tauri/src/operations/directory/mod.rs | 32 +++--- nym-connect/desktop/src-tauri/src/state.rs | 36 +++++- nym-connect/desktop/src-tauri/src/tasks.rs | 14 +-- .../src/components/ConnectionStatus.tsx | 6 +- nym-connect/desktop/src/context/main.tsx | 61 +++++----- .../desktop/src/context/mocks/main.tsx | 4 +- nym-connect/desktop/src/hooks/events.ts | 6 +- .../desktop/src/pages/connection/index.tsx | 3 + nym-connect/desktop/src/pages/menu/index.tsx | 3 +- .../menu/settings/MonitoringSettings.tsx | 12 +- .../menu/settings/PrivacyLevelSettings.tsx | 48 ++++++++ nym-connect/desktop/src/routes/index.tsx | 6 +- nym-connect/desktop/src/types/common.ts | 1 - nym-connect/desktop/src/types/index.ts | 2 +- nym-connect/desktop/src/types/user-data.ts | 6 + 28 files changed, 324 insertions(+), 396 deletions(-) delete mode 100644 .github/workflows/nym-connect-s-publish-macos.yml delete mode 100644 .github/workflows/nym-connect-s-publish-ubuntu.yml delete mode 100644 .github/workflows/nym-connect-s-publish-windows10.yml create mode 100644 nym-connect/desktop/src-tauri/src/config/user_data.rs create mode 100644 nym-connect/desktop/src/pages/menu/settings/PrivacyLevelSettings.tsx delete mode 100644 nym-connect/desktop/src/types/common.ts create mode 100644 nym-connect/desktop/src/types/user-data.ts diff --git a/.github/workflows/nym-connect-s-publish-macos.yml b/.github/workflows/nym-connect-s-publish-macos.yml deleted file mode 100644 index d4b50860d6..0000000000 --- a/.github/workflows/nym-connect-s-publish-macos.yml +++ /dev/null @@ -1,104 +0,0 @@ -name: Publish Nym Connect - desktop (MacOS) -on: - workflow_dispatch: - inputs: - release_tag: - required: true - description: Release tag (nym-connect-s-v*) - type: string - default: 'nym-connect-s-v1.0.0' - push: - tags: - - nym-connect-s-v* - -defaults: - run: - working-directory: nym-connect/desktop - -jobs: - publish-tauri: - if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }} - strategy: - fail-fast: false - matrix: - platform: [macos-latest] - runs-on: ${{ matrix.platform }} - - steps: - - uses: actions/checkout@v2 - - - name: Node - uses: actions/setup-node@v3 - with: - node-version: 18 - - name: Install Rust stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - - name: Install the Apple developer certificate for code signing - env: - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - run: | - # create variables - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - - # import certificate and provisioning profile from secrets - echo -n "$APPLE_CERTIFICATE" | base64 --decode --output $CERTIFICATE_PATH - - # create temporary keychain - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - - # import certificate to keychain - security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH - - - name: Create env file - uses: timheuer/base64-to-file@v1.2 - with: - fileName: '.env' - encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }} - - - name: Prepare for build - env: - RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }} - run: ./scripts/pre_medium_build.sh - - - name: Install app dependencies and build it - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} - APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} - APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_IDENTITY_ID }} - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - NYM_CONNECT_ENABLE_MEDIUM: 1 - run: yarn && yarn build - - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: nym-connect-s_1.0.0_x64.dmg - path: nym-connect/desktop/target/release/bundle/dmg/nym-connect-s_1*_x64.dmg - retention-days: 30 - - - name: Clean up keychain - if: ${{ always() }} - run: | - security delete-keychain $RUNNER_TEMP/app-signing.keychain-db - - - id: create-release - name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 - if: github.event_name == 'release' - with: - files: | - nym-connect/desktop/target/release/bundle/dmg/*.dmg - nym-connect/desktop/target/release/bundle/macos/*.app.tar.gz* diff --git a/.github/workflows/nym-connect-s-publish-ubuntu.yml b/.github/workflows/nym-connect-s-publish-ubuntu.yml deleted file mode 100644 index 204a59a87b..0000000000 --- a/.github/workflows/nym-connect-s-publish-ubuntu.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: Publish NymConnect S - desktop (Ubuntu) -on: - workflow_dispatch: - inputs: - release_tag: - required: true - description: Release tag (nym-connect-s-v*) - type: string - default: 'nym-connect-s-v1.0.0' - push: - tags: - - nym-connect-s-v* - -defaults: - run: - working-directory: nym-connect/desktop - -jobs: - publish-tauri: - if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }} - strategy: - fail-fast: false - matrix: - platform: [custom-runner-linux] - runs-on: ${{ matrix.platform }} - - steps: - - uses: actions/checkout@v2 - - - name: Tauri dependencies - run: > - sudo apt-get update && - sudo apt-get install -y webkit2gtk-4.0 libayatana-appindicator3-dev - continue-on-error: true - - - name: Node - uses: actions/setup-node@v3 - with: - node-version: 18 - - - name: Install Rust stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - - - name: Install project dependencies - shell: bash - run: cd .. && yarn --network-timeout 100000 - - - name: Install app dependencies - run: yarn - - - name: Create env file - uses: timheuer/base64-to-file@v1.2 - with: - fileName: '.env' - encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }} - - - name: Prepare for build - env: - RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }} - run: ./scripts/pre_medium_build.sh - - - name: Build app - run: yarn build - env: - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - NYM_CONNECT_ENABLE_MEDIUM: 1 - - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: nym-connect-s.AppImage.tar.gz - path: nym-connect/desktop/target/release/bundle/appimage/nym-connect-s_1*_amd64.AppImage - retention-days: 30 - - - id: create-release - name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 - if: github.event_name == 'release' - with: - files: | - nym-connect/desktop/target/release/bundle/appimage/*.AppImage - nym-connect/desktop/target/release/bundle/appimage/*.AppImage.tar.gz* diff --git a/.github/workflows/nym-connect-s-publish-windows10.yml b/.github/workflows/nym-connect-s-publish-windows10.yml deleted file mode 100644 index 06d0847b95..0000000000 --- a/.github/workflows/nym-connect-s-publish-windows10.yml +++ /dev/null @@ -1,104 +0,0 @@ -name: Publish Nym Connect - desktop (Windows 10) -on: - workflow_dispatch: - inputs: - release_tag: - required: true - description: Release tag (nym-connect-s-v*) - type: string - default: 'nym-connect-s-v1.0.0' - push: - tags: - - nym-connect-s-v* - -defaults: - run: - working-directory: nym-connect/desktop - -jobs: - publish-tauri: - if: ${{ (startsWith(github.ref, 'refs/tags/nym-connect-s-') && github.event_name == 'release') || github.event_name == 'workflow_dispatch' }} - strategy: - fail-fast: false - matrix: - platform: [windows10] - runs-on: ${{ matrix.platform }} - - steps: - - name: Clean up first - continue-on-error: true - working-directory: . - run: | - cd .. - del /s /q /A:H nym - rmdir /s /q nym - - - uses: actions/checkout@v3 - - - name: Import signing certificate - env: - WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} - WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} - run: | - New-Item -ItemType directory -Path certificate - Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE - certutil -decode certificate/tempCert.txt certificate/certificate.pfx - Remove-Item -path certificate -include tempCert.txt - Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText) - - - name: Node - uses: actions/setup-node@v3 - with: - node-version: 18 - - - name: Install Rust stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - - - name: Create env file - uses: timheuer/base64-to-file@v1.2 - with: - fileName: '.env' - encodedString: ${{ secrets.WALLET_ADMIN_ADDRESS }} - - - name: Install project dependencies - shell: bash - run: cd .. && yarn --network-timeout 100000 - - - name: Install app dependencies - shell: bash - run: yarn --network-timeout 100000 - - - name: Prepare for build - env: - RELEASE_TAG: ${{ github.ref_name || inputs.release_tag }} - run: ./scripts/pre_medium_build.sh - - - name: Build and sign it - shell: bash - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ENABLE_CODE_SIGNING: ${{ secrets.WINDOWS_CERTIFICATE }} - WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }} - WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} - TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} - TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} - NYM_CONNECT_ENABLE_MEDIUM: 1 - run: yarn build - - - name: Upload Artifact - uses: actions/upload-artifact@v3 - with: - name: nym-connect-s_1.0.0_x64_en-US.msi - path: nym-connect/desktop/target/release/bundle/msi/nym-connect-s_1*_x64_en-US.msi - retention-days: 30 - - - id: create-release - name: Upload to release based on tag name - uses: softprops/action-gh-release@v1 - if: github.event_name == 'release' - with: - files: | - nym-connect/desktop/target/release/bundle/msi/*.msi - nym-connect/desktop/target/release/bundle/msi/*.msi.zip* diff --git a/nym-connect/desktop/Cargo.lock b/nym-connect/desktop/Cargo.lock index 4b515a4f54..a5c4fe58a1 100644 --- a/nym-connect/desktop/Cargo.lock +++ b/nym-connect/desktop/Cargo.lock @@ -1532,6 +1532,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "equivalent" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" + [[package]] name = "errno" version = "0.2.8" @@ -2217,7 +2223,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.2", "slab", "tokio", "tokio-util", @@ -2256,6 +2262,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "hashlink" version = "0.7.0" @@ -2618,6 +2630,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", +] + [[package]] name = "infer" version = "0.7.0" @@ -3462,6 +3484,7 @@ dependencies = [ "thiserror", "time", "tokio", + "toml 0.7.4", "ts-rs", "url", "yaml-rust", @@ -4530,7 +4553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bd9647b268a3d3e14ff09c23201133a62589c658db02bb7388c7246aafe0590" dependencies = [ "base64 0.21.2", - "indexmap", + "indexmap 1.9.2", "line-wrap", "quick-xml 0.28.1", "serde", @@ -5129,7 +5152,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02c613288622e5f0c3fdc5dbd4db1c5fbe752746b1d1a56a0630b78fd00de44f" dependencies = [ "dyn-clone", - "indexmap", + "indexmap 1.9.2", "schemars_derive", "serde", "serde_json", @@ -5345,9 +5368,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d" +checksum = "96426c9936fd7a0124915f9185ea1d20aa9445cc9821142f0a73bc9207a2e186" dependencies = [ "serde", ] @@ -5677,7 +5700,7 @@ dependencies = [ "futures-util", "hashlink 0.7.0", "hex", - "indexmap", + "indexmap 1.9.2", "itoa 1.0.6", "libc", "libsqlite3-sys", @@ -5723,7 +5746,7 @@ dependencies = [ "futures-util", "hashlink 0.8.1", "hex", - "indexmap", + "indexmap 1.9.2", "itoa 1.0.6", "libc", "libsqlite3-sys", @@ -6580,20 +6603,20 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.19.10" +version = "0.19.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +checksum = "c500344a19072298cd05a7224b3c0c629348b78692bf48466c5238656e315a78" dependencies = [ - "indexmap", + "indexmap 2.0.0", "serde", "serde_spanned", "toml_datetime", diff --git a/nym-connect/desktop/src-tauri/Cargo.toml b/nym-connect/desktop/src-tauri/Cargo.toml index ffd4c43461..fb4b06a1df 100644 --- a/nym-connect/desktop/src-tauri/Cargo.toml +++ b/nym-connect/desktop/src-tauri/Cargo.toml @@ -43,7 +43,7 @@ time = { version = "0.3.17", features = ["local-offset"] } tokio = { version = "1.24.1", features = ["sync", "time"] } url = "2.2" yaml-rust = "0.4" - +toml = "0.7" nym-client-core = { path = "../../../common/client-core" } nym-api-requests = { path = "../../../nym-api/nym-api-requests" } diff --git a/nym-connect/desktop/src-tauri/src/build.rs b/nym-connect/desktop/src-tauri/src/build.rs index 2c8232a54b..261851f6b6 100644 --- a/nym-connect/desktop/src-tauri/src/build.rs +++ b/nym-connect/desktop/src-tauri/src/build.rs @@ -1,10 +1,3 @@ -use std::env; - fn main() { - if env::var_os("NYM_CONNECT_ENABLE_MEDIUM").is_some() { - println!("cargo:rustc-cfg=medium_enabled"); - } - println!("cargo:rerun-if-changed=build.rs"); - tauri_build::build(); } diff --git a/nym-connect/desktop/src-tauri/src/config/mod.rs b/nym-connect/desktop/src-tauri/src/config/mod.rs index 3c76500aab..f2cbff0d46 100644 --- a/nym-connect/desktop/src-tauri/src/config/mod.rs +++ b/nym-connect/desktop/src-tauri/src/config/mod.rs @@ -26,6 +26,10 @@ mod old_config_v1_1_20_2; mod persistence; mod template; mod upgrade; +mod user_data; + +pub use user_data::PrivacyLevel; +pub use user_data::UserData; static SOCKS5_CONFIG_ID: &str = "nym-connect"; diff --git a/nym-connect/desktop/src-tauri/src/config/user_data.rs b/nym-connect/desktop/src-tauri/src/config/user_data.rs new file mode 100644 index 0000000000..3e9287f375 --- /dev/null +++ b/nym-connect/desktop/src-tauri/src/config/user_data.rs @@ -0,0 +1,67 @@ +use eyre::{eyre, Context, Result}; +use log::error; +use serde::{Deserialize, Serialize}; +use std::{fs, str}; +use tauri::api::path::data_dir; + +const DATA_DIR: &str = "nym-connect"; +const DATA_FILE: &str = "user-data.toml"; + +#[derive(Serialize, Deserialize, Debug, Copy, Clone, Default)] +pub enum PrivacyLevel { + #[default] + High, + Medium, +} + +// User data is read from and write on disk +// Linux: $XDG_DATA_HOME or $HOME/.local/share/ +// macOS: $HOME/Library/Application Support +// Windows: {FOLDERID_RoamingAppData} +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct UserData { + pub monitoring: Option, + pub privacy_level: Option, +} + +fn create_directory_path() -> Result<()> { + let mut data_dir = data_dir().ok_or(eyre!("Failed to retrieve data directory"))?; + data_dir.push(DATA_DIR); + + fs::create_dir_all(&data_dir).context(format!( + "Failed to create user data directory path {}", + data_dir.display() + )) +} + +impl UserData { + pub fn read() -> Result { + // create the full directory path if it is missing + create_directory_path()?; + + let mut data_path = data_dir().ok_or(eyre!("Failed to retrieve data directory"))?; + + data_path.push(DATA_DIR); + data_path.push(DATA_FILE); + let content = fs::read(&data_path) + .context(format!("Failed to read user data {}", data_path.display()))?; + + toml::from_str::(str::from_utf8(&content)?).map_err(|e| { + error!("{}", e); + eyre!("{e}") + }) + } + + pub fn write(&self) -> Result<()> { + // create the full directory path if it is missing + create_directory_path()?; + + let mut data_path = data_dir().ok_or(eyre!("Failed to retrieve data directory"))?; + + data_path.push(DATA_DIR); + data_path.push(DATA_FILE); + let toml = toml::to_string(&self)?; + fs::write(data_path, toml)?; + Ok(()) + } +} diff --git a/nym-connect/desktop/src-tauri/src/error.rs b/nym-connect/desktop/src-tauri/src/error.rs index 0540f01daf..651e741aea 100644 --- a/nym-connect/desktop/src-tauri/src/error.rs +++ b/nym-connect/desktop/src-tauri/src/error.rs @@ -70,6 +70,8 @@ pub enum BackendError { NewWindowError, #[error("unable to parse the specified gateway")] UnableToParseGateway, + #[error("unable to write user data to disk")] + UserDataWriteError, #[error("unable to load keys: {source}")] UnableToLoadKeys { diff --git a/nym-connect/desktop/src-tauri/src/main.rs b/nym-connect/desktop/src-tauri/src/main.rs index f41f401812..8a926938d1 100644 --- a/nym-connect/desktop/src-tauri/src/main.rs +++ b/nym-connect/desktop/src-tauri/src/main.rs @@ -9,8 +9,9 @@ use nym_config::defaults::setup_env; use tauri::Manager; use tokio::sync::RwLock; +use crate::config::UserData; use crate::menu::{create_tray_menu, tray_menu_event_handler}; -use crate::state::{is_medium_enabled, State}; +use crate::state::State; use crate::window::window_toggle; mod config; @@ -25,12 +26,6 @@ mod tasks; mod window; fn main() { - if is_medium_enabled() { - println!("medium mode enabled"); - std::env::set_var("NYM_CONNECT_DISABLE_COVER", "1"); - std::env::set_var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS", "1"); - std::env::set_var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS", "1"); - } setup_env(None); println!("Starting up..."); @@ -40,13 +35,22 @@ fn main() { log::warn!("Failed to fix PATH: {error}"); } + let user_data = UserData::read().unwrap_or_else(|e| { + println!("{}", e); + println!("Fallback to default"); + UserData::default() + }); + let context = tauri::generate_context!(); tauri::Builder::default() - .manage(Arc::new(RwLock::new(State::new()))) + .manage(Arc::new(RwLock::new(State::new(user_data)))) .invoke_handler(tauri::generate_handler![ crate::operations::config::get_config_file_location, crate::operations::config::get_config_id, crate::operations::common::get_env, + crate::operations::common::get_user_data, + crate::operations::common::set_monitoring, + crate::operations::common::set_privacy_level, crate::operations::connection::connect::get_gateway, crate::operations::connection::connect::get_service_provider, crate::operations::connection::connect::set_gateway, @@ -57,7 +61,6 @@ fn main() { crate::operations::connection::status::get_connection_status, crate::operations::connection::status::get_gateway_connection_status, crate::operations::connection::status::start_connection_health_check_task, - crate::operations::connection::status::is_medium_mode_enabled, crate::operations::directory::get_services, crate::operations::directory::get_gateways_detailed, crate::operations::export::export_keys, diff --git a/nym-connect/desktop/src-tauri/src/operations/common.rs b/nym-connect/desktop/src-tauri/src/operations/common.rs index 707dd19860..a4e9604d60 100644 --- a/nym-connect/desktop/src-tauri/src/operations/common.rs +++ b/nym-connect/desktop/src-tauri/src/operations/common.rs @@ -1,4 +1,9 @@ +use crate::config::PrivacyLevel; +use crate::error::Result; +use crate::{config::UserData, state::State}; use std::env; +use std::sync::Arc; +use tokio::sync::RwLock; #[tauri::command] pub async fn get_env(variable: String) -> Option { @@ -7,3 +12,27 @@ pub async fn get_env(variable: String) -> Option { var } + +#[tauri::command] +pub async fn get_user_data(state: tauri::State<'_, Arc>>) -> Result { + let guard = state.read().await; + Ok(guard.get_user_data().clone()) +} + +#[tauri::command] +pub async fn set_monitoring( + enabled: bool, + state: tauri::State<'_, Arc>>, +) -> Result<()> { + let mut guard = state.write().await; + guard.set_monitoring(enabled) +} + +#[tauri::command] +pub async fn set_privacy_level( + privacy_level: PrivacyLevel, + state: tauri::State<'_, Arc>>, +) -> Result<()> { + let mut guard = state.write().await; + guard.set_privacy_level(privacy_level) +} diff --git a/nym-connect/desktop/src-tauri/src/operations/connection/connect.rs b/nym-connect/desktop/src-tauri/src/operations/connection/connect.rs index 1d83748698..95a125fa30 100644 --- a/nym-connect/desktop/src-tauri/src/operations/connection/connect.rs +++ b/nym-connect/desktop/src-tauri/src/operations/connection/connect.rs @@ -12,6 +12,7 @@ pub async fn start_connecting( window: tauri::Window, ) -> Result { log::trace!("Start connecting"); + let (msg_receiver, exit_status_receiver) = { let mut state_w = state.write().await; state_w.start_connecting(&window).await? diff --git a/nym-connect/desktop/src-tauri/src/operations/connection/status.rs b/nym-connect/desktop/src-tauri/src/operations/connection/status.rs index 8391f724cf..7710524fb5 100644 --- a/nym-connect/desktop/src-tauri/src/operations/connection/status.rs +++ b/nym-connect/desktop/src-tauri/src/operations/connection/status.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use tokio::sync::RwLock; use crate::models::{ConnectionStatusKind, ConnectivityTestResult, GatewayConnectionStatusKind}; -use crate::state::{is_medium_enabled, State}; +use crate::state::State; #[tauri::command] pub async fn get_connection_status( @@ -42,8 +42,3 @@ pub fn start_connection_health_check_task( ) { tasks::start_connection_check(state.inner().clone(), window); } - -#[tauri::command] -pub async fn is_medium_mode_enabled(_state: tauri::State<'_, Arc>>) -> Result { - Ok(is_medium_enabled()) -} diff --git a/nym-connect/desktop/src-tauri/src/operations/directory/mod.rs b/nym-connect/desktop/src-tauri/src/operations/directory/mod.rs index 77bd2b8e84..0b1d36819f 100644 --- a/nym-connect/desktop/src-tauri/src/operations/directory/mod.rs +++ b/nym-connect/desktop/src-tauri/src/operations/directory/mod.rs @@ -1,12 +1,15 @@ use itertools::Itertools; +use crate::config::PrivacyLevel; use crate::error::Result; use crate::models::{ DirectoryService, DirectoryServiceProvider, HarbourMasterService, PagedResult, }; -use crate::state::is_medium_enabled; +use crate::state::State; use nym_api_requests::models::GatewayBondAnnotated; use nym_contracts_common::types::Percent; +use std::sync::Arc; +use tokio::sync::RwLock; static SERVICE_PROVIDER_WELLKNOWN_URL: &str = "https://nymtech.net/.wellknown/connect/service-providers.json"; @@ -20,21 +23,20 @@ static HARBOUR_MASTER_URL: &str = "https://harbourmaster.nymtech.net/v1/services static GATEWAYS_DETAILED_URL: &str = "https://validator.nymtech.net/api/v1/status/gateways/detailed"; -fn get_services_url() -> &'static str { - if is_medium_enabled() { - return SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM; - } - SERVICE_PROVIDER_WELLKNOWN_URL -} - #[tauri::command] -pub async fn get_services() -> Result> { +pub async fn get_services( + state: tauri::State<'_, Arc>>, +) -> Result> { log::trace!("Fetching services"); - let all_services = fetch_services().await?; + + let guard = state.read().await; + let privacy_level = guard.get_user_data().privacy_level.unwrap_or_default(); + + let all_services = fetch_services(&privacy_level).await?; log::trace!("Received: {:#?}", all_services); // Early return if we're running with medium toggle enabled - if is_medium_enabled() { + if let PrivacyLevel::Medium = privacy_level { return Ok(all_services.into_iter().flat_map(|sp| sp.items).collect()); } @@ -100,8 +102,12 @@ fn filter_out_poor_gateways( .collect() } -async fn fetch_services() -> Result> { - let services_url = get_services_url(); +async fn fetch_services(privacy_level: &PrivacyLevel) -> Result> { + let services_url = match privacy_level { + PrivacyLevel::Medium => SERVICE_PROVIDER_WELLKNOWN_URL_MEDIUM, + _ => SERVICE_PROVIDER_WELLKNOWN_URL, + }; + let services_res = reqwest::get(services_url) .await? .json::>() diff --git a/nym-connect/desktop/src-tauri/src/state.rs b/nym-connect/desktop/src-tauri/src/state.rs index b44ca16107..044b185b86 100644 --- a/nym-connect/desktop/src-tauri/src/state.rs +++ b/nym-connect/desktop/src-tauri/src/state.rs @@ -1,4 +1,5 @@ use futures::SinkExt; +use log::error; use nym_client_core::error::ClientCoreStatusMessage; use nym_socks5_client_core::{Socks5ControlMessage, Socks5ControlMessageSender}; use std::time::Duration; @@ -7,6 +8,8 @@ use tauri::Manager; use tokio::time::Instant; use crate::config::Config; +use crate::config::PrivacyLevel; +use crate::config::UserData; use crate::{ config::{self, socks5_config_id_appended_with}, error::{BackendError, Result}, @@ -65,10 +68,13 @@ pub struct State { /// The latest end-to-end connectivity test result. The first test is initiated on connection /// established. Additional tests can be triggered. connectivity_test_result: ConnectivityTestResult, + + /// User data saved on disk, like user settings + user_data: UserData, } impl State { - pub fn new() -> Self { + pub fn new(user_data: UserData) -> Self { State { status: ConnectionStatusKind::Disconnected, service_provider: None, @@ -76,6 +82,7 @@ impl State { socks5_client_sender: None, gateway_connectivity: GatewayConnectivity::Good, connectivity_test_result: ConnectivityTestResult::NotAvailable, + user_data, } } @@ -93,6 +100,26 @@ impl State { self.gateway_connectivity } + pub fn get_user_data(&self) -> &UserData { + &self.user_data + } + + pub fn set_monitoring(&mut self, enabled: bool) -> Result<()> { + self.user_data.monitoring = Some(enabled); + self.user_data.write().map_err(|e| { + error!("Failed to write user data to disk {e}"); + BackendError::UserDataWriteError + }) + } + + pub fn set_privacy_level(&mut self, privacy_level: PrivacyLevel) -> Result<()> { + self.user_data.privacy_level = Some(privacy_level); + self.user_data.write().map_err(|e| { + error!("Failed to write user data to disk {e}"); + BackendError::UserDataWriteError + }) + } + pub fn set_gateway_connectivity(&mut self, gateway_connectivity: GatewayConnectivity) { self.gateway_connectivity = gateway_connectivity } @@ -200,8 +227,9 @@ impl State { &mut self, ) -> Result<(nym_task::StatusReceiver, ExitStatusReceiver)> { let id = self.get_config_id()?; + let privacy_level = self.user_data.privacy_level.unwrap_or_default(); let (control_tx, msg_rx, exit_status_rx, used_gateway) = - tasks::start_nym_socks5_client(&id).await?; + tasks::start_nym_socks5_client(&id, &privacy_level).await?; self.socks5_client_sender = Some(control_tx); self.gateway = Some(used_gateway.gateway_id); Ok((msg_rx, exit_status_rx)) @@ -244,7 +272,3 @@ impl State { self.set_state(ConnectionStatusKind::Disconnected, window); } } - -pub fn is_medium_enabled() -> bool { - cfg!(medium_enabled) || std::env::var("NYM_CONNECT_ENABLE_MEDIUM").is_ok() -} diff --git a/nym-connect/desktop/src-tauri/src/tasks.rs b/nym-connect/desktop/src-tauri/src/tasks.rs index d6ac1b0918..8c69b1be7e 100644 --- a/nym-connect/desktop/src-tauri/src/tasks.rs +++ b/nym-connect/desktop/src-tauri/src/tasks.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use tap::TapFallible; use tokio::sync::RwLock; -use crate::config::Config; +use crate::config::{Config, PrivacyLevel}; use crate::{ error::Result, events::{self, emit_event, emit_status_event}, @@ -30,23 +30,20 @@ pub enum Socks5ExitStatusMessage { Failed(Box), } -fn override_config_from_env(config: &mut Config) { +fn override_config_from_env(config: &mut Config, privacy_level: &PrivacyLevel) { // Disable both the loop cover traffic that runs in the background as well as the Poisson // process that injects cover traffic into the traffic stream. - if std::env::var("NYM_CONNECT_DISABLE_COVER").is_ok() { + if let PrivacyLevel::Medium = privacy_level { + log::info!("Running in Medium privacy level"); log::warn!("Disabling cover traffic"); config.core.base.set_no_cover_traffic_with_keepalive(); - } - if std::env::var("NYM_CONNECT_ENABLE_MIXED_SIZE_PACKETS").is_ok() { log::warn!("Enabling mixed size packets"); config .core .base .set_secondary_packet_size(Some(PacketSize::ExtendedPacket16)); - } - if std::env::var("NYM_CONNECT_DISABLE_PER_HOP_DELAYS").is_ok() { log::warn!("Disabling per-hop delay"); config.core.base.set_no_per_hop_delays(); } @@ -55,6 +52,7 @@ fn override_config_from_env(config: &mut Config) { /// The main SOCKS5 client task. It loads the configuration from file determined by the `id`. pub async fn start_nym_socks5_client( id: &str, + privacy_level: &PrivacyLevel, ) -> Result<( Socks5ControlMessageSender, nym_task::StatusReceiver, @@ -65,7 +63,7 @@ pub async fn start_nym_socks5_client( let mut config = Config::read_from_default_path(id) .tap_err(|_| log::warn!("Failed to load configuration file"))?; - override_config_from_env(&mut config); + override_config_from_env(&mut config, privacy_level); log::trace!("Configuration used: {:#?}", config); diff --git a/nym-connect/desktop/src/components/ConnectionStatus.tsx b/nym-connect/desktop/src/components/ConnectionStatus.tsx index c23abdb7d8..73fb6bf992 100644 --- a/nym-connect/desktop/src/components/ConnectionStatus.tsx +++ b/nym-connect/desktop/src/components/ConnectionStatus.tsx @@ -16,7 +16,7 @@ const ConnectionStatusContent: FCWithChildren<{ serviceProvider?: ServiceProvider; gatewayError: boolean; }> = ({ status, serviceProvider, gatewayError }) => { - const { speedMode } = useClientContext(); + const { userData } = useClientContext(); if (gatewayError) { return ( @@ -49,10 +49,10 @@ const ConnectionStatusContent: FCWithChildren<{ - {speedMode === 'medium' && ( + {userData?.privacy_level === 'Medium' && ( - Speedy mode activated + Speed boost activated )} diff --git a/nym-connect/desktop/src/context/main.tsx b/nym-connect/desktop/src/context/main.tsx index 462c425800..f51e73389d 100644 --- a/nym-connect/desktop/src/context/main.tsx +++ b/nym-connect/desktop/src/context/main.tsx @@ -3,23 +3,24 @@ import { DateTime } from 'luxon'; import { invoke } from '@tauri-apps/api'; import { Error } from 'src/types/error'; import { getVersion } from '@tauri-apps/api/app'; +import * as Sentry from '@sentry/react'; import { useEvents } from 'src/hooks/events'; import { UserDefinedGateway, UserDefinedSPAddress } from 'src/types/service-provider'; import { getItemFromStorage, setItemInStorage } from 'src/utils'; -import { ConnectionStatusKind, GatewayPerformance, SpeedMode } from '../types'; +import { ConnectionStatusKind, GatewayPerformance, PrivacyLevel, UserData } from '../types'; import { ConnectionStatsItem } from '../components/ConnectionStats'; import { ServiceProvider } from '../types/directory'; import initSentry from '../sentry'; const FORAGE_GATEWAY_KEY = 'nym-connect-user-gateway'; const FORAGE_SP_KEY = 'nym-connect-user-sp'; -const FORAGE_MONITORING_ENABLED = 'nym-connect-monitoring-enabled'; type ModeType = 'light' | 'dark'; export type TClientContext = { mode: ModeType; appVersion?: string; + userData?: UserData; connectionStatus: ConnectionStatusKind; connectionStats?: ConnectionStatsItem[]; connectedSince?: DateTime; @@ -32,7 +33,6 @@ export type TClientContext = { serviceProviders?: ServiceProvider[]; setMode: (mode: ModeType) => void; clearError: () => void; - monitoringEnabled: boolean; setConnectionStatus: (connectionStatus: ConnectionStatusKind) => void; setConnectionStats: (connectionStats: ConnectionStatsItem[] | undefined) => void; setConnectedSince: (connectedSince: DateTime | undefined) => void; @@ -43,7 +43,7 @@ export type TClientContext = { setUserDefinedGateway: React.Dispatch>; setUserDefinedSPAddress: React.Dispatch>; setMonitoring: (value: boolean) => Promise; - speedMode: SpeedMode; + setPrivacyLevel: (value: PrivacyLevel) => Promise; }; export const ClientContext = createContext({} as TClientContext); @@ -67,19 +67,26 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { isActive: false, address: undefined, }); - const [monitoringEnabled, setMonitoringEnabled] = useState(false); - const [speedMode, setspeedMode] = useState('slow'); + const [userData, setUserData] = useState(); const getAppVersion = async () => { const version = await getVersion(); return version; }; + const getUserData = async () => { + const data = await invoke('get_user_data'); + if (!data.privacy_level) { + data.privacy_level = 'High'; + } + setUserData(data); + return data; + }; + useEffect(() => { const initSentryClient = async () => { - const monitoring = await getItemFromStorage({ key: FORAGE_MONITORING_ENABLED }); - setMonitoringEnabled(Boolean(monitoring)); - if (monitoring === true) { + const data = await getUserData(); + if (data.monitoring) { await initSentry(); } }; @@ -87,17 +94,6 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { initSentryClient(); }, []); - useEffect(() => { - const initSpeedMode = async () => { - const isEnabled = await invoke('is_medium_mode_enabled'); - if (isEnabled) { - setspeedMode('medium'); - } - }; - - initSpeedMode(); - }, []); - useEffect(() => { setItemInStorage({ key: FORAGE_GATEWAY_KEY, value: userDefinedGateway }); }, [userDefinedGateway]); @@ -124,7 +120,10 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { }; useEvents({ - onError: (e) => setError(e), + onError: (e) => { + setError(e); + Sentry.captureException(e); + }, onGatewayPerformanceChange: (performance) => setGatewayPerformance(performance), onStatusChange: (status) => setConnectionStatus(status), }); @@ -147,6 +146,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { } catch (e) { setError({ title: 'Could not connect', message: e as string }); console.log(e); + Sentry.captureException(e); } }, []); @@ -155,6 +155,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { await invoke('start_disconnecting'); } catch (e) { console.log(e); + Sentry.captureException(e); } }, []); @@ -197,8 +198,15 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { const clearError = () => setError(undefined); const setMonitoring = async (value: boolean) => { - setMonitoringEnabled(value); - await setItemInStorage({ key: FORAGE_MONITORING_ENABLED, value }); + await invoke('set_monitoring', { enabled: value }); + // refresh user data + await getUserData(); + }; + + const setPrivacyLevel = async (value: PrivacyLevel) => { + await invoke('set_privacy_level', { privacyLevel: value }); + // refresh user data + await getUserData(); }; const contextValue = useMemo( @@ -216,7 +224,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { selectedProvider, serviceProviders, connectedSince, - monitoringEnabled, + userData, setConnectedSince, setSerivceProvider, startConnecting, @@ -228,7 +236,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { setUserDefinedGateway, setUserDefinedSPAddress, setMonitoring, - speedMode, + setPrivacyLevel, }), [ mode, @@ -244,8 +252,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { selectedProvider, userDefinedGateway, userDefinedSPAddress, - monitoringEnabled, - speedMode, + userData, ], ); diff --git a/nym-connect/desktop/src/context/mocks/main.tsx b/nym-connect/desktop/src/context/mocks/main.tsx index 9ae5495ac8..8fdd8518c9 100644 --- a/nym-connect/desktop/src/context/mocks/main.tsx +++ b/nym-connect/desktop/src/context/mocks/main.tsx @@ -11,8 +11,7 @@ const mockValues: TClientContext = { showInfoModal: false, userDefinedGateway: { isActive: false, gateway: '' }, userDefinedSPAddress: { isActive: false, address: '' }, - monitoringEnabled: false, - speedMode: 'slow', + userData: { monitoring: false, privacy_level: 'High' }, setShowInfoModal: () => {}, setMode: () => {}, clearError: () => {}, @@ -25,6 +24,7 @@ const mockValues: TClientContext = { setUserDefinedGateway: () => {}, setUserDefinedSPAddress: () => {}, setMonitoring: async () => {}, + setPrivacyLevel: async () => {}, }; export const MockProvider: FCWithChildren<{ diff --git a/nym-connect/desktop/src/hooks/events.ts b/nym-connect/desktop/src/hooks/events.ts index 4b2c4fcc55..0b15e5347d 100644 --- a/nym-connect/desktop/src/hooks/events.ts +++ b/nym-connect/desktop/src/hooks/events.ts @@ -1,5 +1,6 @@ import { useEffect, useRef } from 'react'; import { listen, UnlistenFn } from '@tauri-apps/api/event'; +import * as Sentry from '@sentry/react'; import { ConnectionStatusKind, GatewayPerformance } from 'src/types'; import { Error } from 'src/types/error'; import { TauriEvent } from 'src/types/event'; @@ -29,7 +30,10 @@ export const useEvents = ({ .then((result) => { unlisten.push(result); }) - .catch((e) => console.log(e)); + .catch((e) => { + console.log(e); + Sentry.captureException(e); + }); listen('socks5-event', (e: TauriEvent) => { console.log(e); diff --git a/nym-connect/desktop/src/pages/connection/index.tsx b/nym-connect/desktop/src/pages/connection/index.tsx index 2ba081331f..bbdf0a6125 100644 --- a/nym-connect/desktop/src/pages/connection/index.tsx +++ b/nym-connect/desktop/src/pages/connection/index.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { forage } from '@tauri-apps/tauri-forage'; +import * as Sentry from '@sentry/react'; import { DateTime } from 'luxon'; import { useClientContext } from 'src/context/main'; import { useTauriEvents } from 'src/utils'; @@ -28,12 +29,14 @@ export const ConnectionPage = () => { // eslint-disable-next-line default-case switch (currentStatus) { case 'disconnected': + Sentry.captureMessage('start connect', 'info'); await context.setSerivceProvider(); await context.startConnecting(); context.setConnectedSince(DateTime.now()); context.setShowInfoModal(true); break; case 'connected': + Sentry.captureMessage('start disconnect', 'info'); await context.startDisconnecting(); context.setConnectedSince(undefined); break; diff --git a/nym-connect/desktop/src/pages/menu/index.tsx b/nym-connect/desktop/src/pages/menu/index.tsx index da4f2be73d..67576dc88c 100644 --- a/nym-connect/desktop/src/pages/menu/index.tsx +++ b/nym-connect/desktop/src/pages/menu/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Apps, HelpOutline, Settings, BugReport } from '@mui/icons-material'; +import { Apps, HelpOutline, Settings, BugReport, PrivacyTip } from '@mui/icons-material'; import { Stack, Link, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material'; import { Link as RouterLink } from 'react-router-dom'; import { AppVersion } from 'src/components/AppVersion'; @@ -7,6 +7,7 @@ import { AppVersion } from 'src/components/AppVersion'; const menuSchema = [ { title: 'Supported apps', icon: Apps, path: 'apps' }, { title: 'How to connect guide', icon: HelpOutline, path: 'guide' }, + { title: 'Privacy level', icon: PrivacyTip, path: 'privacy-level' }, { title: 'Please help us improve the app', icon: BugReport, path: 'monitoring' }, { title: 'Settings', icon: Settings, path: 'settings' }, ]; diff --git a/nym-connect/desktop/src/pages/menu/settings/MonitoringSettings.tsx b/nym-connect/desktop/src/pages/menu/settings/MonitoringSettings.tsx index 92e15a155d..8b899cbe72 100644 --- a/nym-connect/desktop/src/pages/menu/settings/MonitoringSettings.tsx +++ b/nym-connect/desktop/src/pages/menu/settings/MonitoringSettings.tsx @@ -4,8 +4,8 @@ import { Box, FormControl, FormControlLabel, FormHelperText, Stack, Switch, Typo import { useClientContext } from 'src/context/main'; export const MonitoringSettings = () => { - const { monitoringEnabled, setMonitoring } = useClientContext(); - const [enabled, setEnabled] = useState(monitoringEnabled); + const { userData, setMonitoring } = useClientContext(); + const [enabled, setEnabled] = useState(userData?.monitoring || false); const [loading, setLoading] = useState(false); const handleChange = async (e: ChangeEvent) => { @@ -25,7 +25,13 @@ export const MonitoringSettings = () => { + } label="Enable" /> diff --git a/nym-connect/desktop/src/pages/menu/settings/PrivacyLevelSettings.tsx b/nym-connect/desktop/src/pages/menu/settings/PrivacyLevelSettings.tsx new file mode 100644 index 0000000000..5c2241b4d0 --- /dev/null +++ b/nym-connect/desktop/src/pages/menu/settings/PrivacyLevelSettings.tsx @@ -0,0 +1,48 @@ +import React, { ChangeEvent, useState } from 'react'; +import * as Sentry from '@sentry/react'; +import { Box, FormControl, FormControlLabel, FormHelperText, Stack, Switch, Typography } from '@mui/material'; +import { useClientContext } from 'src/context/main'; + +export const PrivacyLevelSettings = () => { + const { userData, setPrivacyLevel } = useClientContext(); + const [speedBoost, setSpeedBoost] = useState(userData?.privacy_level !== 'High'); + const [loading, setLoading] = useState(false); + + const handleChange = async (e: ChangeEvent) => { + setLoading(true); + setSpeedBoost(e.target.checked); + Sentry.captureMessage(`privacy level switched to ${e.target.checked ? 'Medium' : 'High'}`, 'info'); + await setPrivacyLevel(e.target.checked ? 'Medium' : 'High'); + setLoading(false); + }; + + return ( + + + + + Speed boost + + + + } + label="Enable" + /> + + By activating this option, the connection speed will be relatively faster in exchange of relaxing some + protections + + + + + + ); +}; diff --git a/nym-connect/desktop/src/routes/index.tsx b/nym-connect/desktop/src/routes/index.tsx index 8af5a703e3..f1e4b1da67 100644 --- a/nym-connect/desktop/src/routes/index.tsx +++ b/nym-connect/desktop/src/routes/index.tsx @@ -9,14 +9,15 @@ import { SettingsMenu } from 'src/pages/menu/settings'; import { GatewaySettings } from 'src/pages/menu/settings/GatewaySettings'; import { ServiceProviderSettings } from 'src/pages/menu/settings/ServiceProviderSettings'; import { MonitoringSettings } from '../pages/menu/settings/MonitoringSettings'; +import { PrivacyLevelSettings } from '../pages/menu/settings/PrivacyLevelSettings'; import { useClientContext } from '../context/main'; const SentryRoutes = Sentry.withSentryReactRouterV6Routing(Routes); export const AppRoutes = () => { - const { monitoringEnabled } = useClientContext(); + const { userData } = useClientContext(); - const RoutesContainer = monitoringEnabled ? SentryRoutes : Routes; + const RoutesContainer = userData?.monitoring ? SentryRoutes : Routes; return ( @@ -25,6 +26,7 @@ export const AppRoutes = () => { } /> } /> } /> + } /> } /> } /> diff --git a/nym-connect/desktop/src/types/common.ts b/nym-connect/desktop/src/types/common.ts deleted file mode 100644 index d4895499d5..0000000000 --- a/nym-connect/desktop/src/types/common.ts +++ /dev/null @@ -1 +0,0 @@ -export type SpeedMode = 'fast' | 'medium' | 'slow'; diff --git a/nym-connect/desktop/src/types/index.ts b/nym-connect/desktop/src/types/index.ts index f8ea4fd95f..7ebac88588 100644 --- a/nym-connect/desktop/src/types/index.ts +++ b/nym-connect/desktop/src/types/index.ts @@ -1,3 +1,3 @@ export * from './rust'; export * from './connection'; -export * from './common'; +export * from './user-data'; diff --git a/nym-connect/desktop/src/types/user-data.ts b/nym-connect/desktop/src/types/user-data.ts new file mode 100644 index 0000000000..8bd43a941e --- /dev/null +++ b/nym-connect/desktop/src/types/user-data.ts @@ -0,0 +1,6 @@ +export type PrivacyLevel = 'High' | 'Medium'; + +export type UserData = { + monitoring?: boolean; + privacy_level?: PrivacyLevel; +};