From 3317804a8025bfc0fbb5036709ee3584347ffb8d Mon Sep 17 00:00:00 2001 From: pierre Date: Tue, 1 Aug 2023 11:57:57 +0200 Subject: [PATCH] feat(nc-desktop): use userdata storage to save user gateway&sp --- nym-connect/desktop/package.json | 2 +- .../desktop/src-tauri/src/config/mod.rs | 4 +- .../desktop/src-tauri/src/config/user_data.rs | 14 ++++++ nym-connect/desktop/src-tauri/src/main.rs | 2 + .../src-tauri/src/operations/common.rs | 20 +++++++- nym-connect/desktop/src-tauri/src/state.rs | 18 +++++++ .../desktop/src/components/AppWindowFrame.tsx | 2 +- nym-connect/desktop/src/context/main.tsx | 48 +++++++++++-------- .../desktop/src/context/mocks/main.tsx | 2 +- .../pages/menu/settings/GatewaySettings.tsx | 4 +- .../desktop/src/types/service-provider.ts | 2 +- nym-connect/desktop/src/types/user-data.ts | 12 +++++ 12 files changed, 102 insertions(+), 28 deletions(-) diff --git a/nym-connect/desktop/package.json b/nym-connect/desktop/package.json index 30612c08fe..ede5727153 100644 --- a/nym-connect/desktop/package.json +++ b/nym-connect/desktop/package.json @@ -115,4 +115,4 @@ "webpack-merge": "^5.8.0", "yaml-loader": "^0.8.0" } -} \ No newline at end of file +} diff --git a/nym-connect/desktop/src-tauri/src/config/mod.rs b/nym-connect/desktop/src-tauri/src/config/mod.rs index b65abc70d1..f201c2f488 100644 --- a/nym-connect/desktop/src-tauri/src/config/mod.rs +++ b/nym-connect/desktop/src-tauri/src/config/mod.rs @@ -28,8 +28,8 @@ mod template; mod upgrade; mod user_data; -pub use user_data::PrivacyLevel; -pub use user_data::UserData; +pub use user_data::*; +// 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 index 3e9287f375..fb5b0dd2dd 100644 --- a/nym-connect/desktop/src-tauri/src/config/user_data.rs +++ b/nym-connect/desktop/src-tauri/src/config/user_data.rs @@ -14,6 +14,18 @@ pub enum PrivacyLevel { Medium, } +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct SelectedGateway { + address: Option, + is_active: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +pub struct SelectedSp { + address: Option, + is_active: Option, +} + // User data is read from and write on disk // Linux: $XDG_DATA_HOME or $HOME/.local/share/ // macOS: $HOME/Library/Application Support @@ -22,6 +34,8 @@ pub enum PrivacyLevel { pub struct UserData { pub monitoring: Option, pub privacy_level: Option, + pub selected_gateway: Option, + pub selected_sp: Option, } fn create_directory_path() -> Result<()> { diff --git a/nym-connect/desktop/src-tauri/src/main.rs b/nym-connect/desktop/src-tauri/src/main.rs index 32a6758239..fc36d44c96 100644 --- a/nym-connect/desktop/src-tauri/src/main.rs +++ b/nym-connect/desktop/src-tauri/src/main.rs @@ -74,6 +74,8 @@ fn main() { crate::operations::common::get_user_data, crate::operations::common::set_monitoring, crate::operations::common::set_privacy_level, + crate::operations::common::set_selected_gateway, + crate::operations::common::set_selected_sp, crate::operations::connection::connect::get_gateway, crate::operations::connection::connect::get_service_provider, crate::operations::connection::connect::set_gateway, diff --git a/nym-connect/desktop/src-tauri/src/operations/common.rs b/nym-connect/desktop/src-tauri/src/operations/common.rs index a4e9604d60..1b8bd1d1db 100644 --- a/nym-connect/desktop/src-tauri/src/operations/common.rs +++ b/nym-connect/desktop/src-tauri/src/operations/common.rs @@ -1,4 +1,4 @@ -use crate::config::PrivacyLevel; +use crate::config::{PrivacyLevel, SelectedGateway, SelectedSp}; use crate::error::Result; use crate::{config::UserData, state::State}; use std::env; @@ -36,3 +36,21 @@ pub async fn set_privacy_level( let mut guard = state.write().await; guard.set_privacy_level(privacy_level) } + +#[tauri::command] +pub async fn set_selected_gateway( + gateway: Option, + state: tauri::State<'_, Arc>>, +) -> Result<()> { + let mut guard = state.write().await; + guard.set_user_selected_gateway(gateway) +} + +#[tauri::command] +pub async fn set_selected_sp( + service_provider: Option, + state: tauri::State<'_, Arc>>, +) -> Result<()> { + let mut guard = state.write().await; + guard.set_user_selected_sp(service_provider) +} diff --git a/nym-connect/desktop/src-tauri/src/state.rs b/nym-connect/desktop/src-tauri/src/state.rs index 044b185b86..5498fee343 100644 --- a/nym-connect/desktop/src-tauri/src/state.rs +++ b/nym-connect/desktop/src-tauri/src/state.rs @@ -9,6 +9,8 @@ use tokio::time::Instant; use crate::config::Config; use crate::config::PrivacyLevel; +use crate::config::SelectedGateway; +use crate::config::SelectedSp; use crate::config::UserData; use crate::{ config::{self, socks5_config_id_appended_with}, @@ -120,6 +122,22 @@ impl State { }) } + pub fn set_user_selected_gateway(&mut self, gateway: Option) -> Result<()> { + self.user_data.selected_gateway = gateway; + self.user_data.write().map_err(|e| { + error!("Failed to write user data to disk {e}"); + BackendError::UserDataWriteError + }) + } + + pub fn set_user_selected_sp(&mut self, service_provider: Option) -> Result<()> { + self.user_data.selected_sp = service_provider; + 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 } diff --git a/nym-connect/desktop/src/components/AppWindowFrame.tsx b/nym-connect/desktop/src/components/AppWindowFrame.tsx index 90e01fffa7..ca49204e11 100644 --- a/nym-connect/desktop/src/components/AppWindowFrame.tsx +++ b/nym-connect/desktop/src/components/AppWindowFrame.tsx @@ -16,7 +16,7 @@ export const AppWindowFrame: FCWithChildren = ({ children }) => { return () => { // when the user moves away from the settings page and the gateway is not valid // set isActive to false - if (!userDefinedGateway?.gateway) { + if (!userDefinedGateway?.address) { setUserDefinedGateway((current) => ({ ...current, isActive: false })); } }; diff --git a/nym-connect/desktop/src/context/main.tsx b/nym-connect/desktop/src/context/main.tsx index ba6377e90b..320643901f 100644 --- a/nym-connect/desktop/src/context/main.tsx +++ b/nym-connect/desktop/src/context/main.tsx @@ -6,15 +6,11 @@ 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, PrivacyLevel, UserData } from '../types'; import { ConnectionStatsItem } from '../components/ConnectionStats'; import { ServiceProvider, Gateway } from '../types/directory'; import initSentry from '../sentry'; -const FORAGE_GATEWAY_KEY = 'nym-connect-user-gateway'; -const FORAGE_SP_KEY = 'nym-connect-user-sp'; - type ModeType = 'light' | 'dark'; export type TClientContext = { @@ -72,7 +68,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { const [showInfoModal, setShowInfoModal] = useState(false); const [userDefinedGateway, setUserDefinedGateway] = useState({ isActive: false, - gateway: undefined, + address: undefined, }); const [userDefinedSPAddress, setUserDefinedSPAddress] = useState({ isActive: false, @@ -92,6 +88,15 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { data.privacy_level = 'High'; } setUserData(data); + if (data.selected_gateway) { + setUserDefinedGateway({ + address: data.selected_gateway.address, + isActive: data.selected_gateway.is_active || false, + }); + } + if (data.selected_sp) { + setUserDefinedSPAddress({ address: data.selected_sp.address, isActive: data.selected_sp.is_active || false }); + } return data; }; @@ -107,30 +112,35 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { }, []); useEffect(() => { - setItemInStorage({ key: FORAGE_GATEWAY_KEY, value: userDefinedGateway }); + const saveUserGateway = async () => { + console.log('******** SAVE GATEWAY'); + console.log(userDefinedGateway); + await invoke('set_selected_gateway', { + gateway: { address: userDefinedGateway.address, is_active: userDefinedGateway.isActive }, + }); + }; + saveUserGateway(); }, [userDefinedGateway]); useEffect(() => { - setItemInStorage({ key: FORAGE_SP_KEY, value: userDefinedSPAddress }); + const saveUserServiceProvider = async () => { + console.log('******** SAVE SP'); + console.log(userDefinedSPAddress); + await invoke('set_selected_sp', { + serviceProvider: { address: userDefinedSPAddress.address, is_active: userDefinedSPAddress.isActive }, + }); + }; + saveUserServiceProvider(); }, [userDefinedSPAddress]); const initialiseApp = async () => { const fetchedServices = await invoke('get_services'); const fetchedGateways = await invoke('get_gateways'); const AppVersion = await getAppVersion(); - const storedUserDefinedGateway = await getItemFromStorage({ key: FORAGE_GATEWAY_KEY }); - const storedUserDefinedSP = await getItemFromStorage({ key: FORAGE_SP_KEY }); setAppVersion(AppVersion); setServiceProviders(fetchedServices); setGateways(fetchedGateways); - - if (storedUserDefinedGateway) { - setUserDefinedGateway(storedUserDefinedGateway); - } - if (storedUserDefinedSP) { - setUserDefinedSPAddress(storedUserDefinedSP); - } }; useEvents({ @@ -179,7 +189,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { } }, []); - const shouldUseUserGateway = !!userDefinedGateway.gateway && userDefinedGateway.isActive; + const shouldUseUserGateway = !!userDefinedGateway.address && userDefinedGateway.isActive; const shouldUseUserSP = !!userDefinedSPAddress.address && userDefinedSPAddress.isActive; const buildServiceProvider = async (serviceProvider: ServiceProvider) => { @@ -190,7 +200,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { const buildGateway = async (gateway: Gateway) => { const gw = { ...gateway }; - if (shouldUseUserGateway) gw.identity = userDefinedGateway.gateway as string; + if (shouldUseUserGateway) gw.identity = userDefinedGateway.address as string; return gw; }; @@ -211,7 +221,7 @@ export const ClientContextProvider: FCWithChildren = ({ children }) => { const randomGateway = getRandomFromList(gateways); const withUserDefinitions = await buildGateway(randomGateway); await invoke('set_gateway', { - gateway: shouldUseUserGateway ? userDefinedGateway.gateway : withUserDefinitions.identity, + gateway: shouldUseUserGateway ? userDefinedGateway.address : withUserDefinitions.identity, }); setSelectedGateway(withUserDefinitions); } diff --git a/nym-connect/desktop/src/context/mocks/main.tsx b/nym-connect/desktop/src/context/mocks/main.tsx index 0b6db34aaf..02de84aa69 100644 --- a/nym-connect/desktop/src/context/mocks/main.tsx +++ b/nym-connect/desktop/src/context/mocks/main.tsx @@ -9,7 +9,7 @@ const mockValues: TClientContext = { selectedProvider: { id: '1', description: 'Keybase service provider', address: '123abc' }, gatewayPerformance: 'Good', showInfoModal: false, - userDefinedGateway: { isActive: false, gateway: '' }, + userDefinedGateway: { isActive: false, address: '' }, userDefinedSPAddress: { isActive: false, address: '' }, userData: { monitoring: false, privacy_level: 'High' }, showFeedbackNote: false, diff --git a/nym-connect/desktop/src/pages/menu/settings/GatewaySettings.tsx b/nym-connect/desktop/src/pages/menu/settings/GatewaySettings.tsx index 80efa7988a..c4de721ef8 100644 --- a/nym-connect/desktop/src/pages/menu/settings/GatewaySettings.tsx +++ b/nym-connect/desktop/src/pages/menu/settings/GatewaySettings.tsx @@ -7,7 +7,7 @@ import { AppVersion } from 'src/components/AppVersion'; export const GatewaySettings = () => { const { userDefinedGateway, setUserDefinedGateway, connectionStatus } = useClientContext(); - const [gatewayKey, setGatewayKey] = useState(userDefinedGateway?.gateway); + const [gatewayKey, setGatewayKey] = useState(userDefinedGateway?.address); const handleIsValidGatewayKey = (isValid: boolean) => { let gateway: string | undefined; @@ -16,7 +16,7 @@ export const GatewaySettings = () => { gateway = gatewayKey; } - setUserDefinedGateway((current) => ({ ...current, gateway })); + setUserDefinedGateway((current) => ({ ...current, address: gateway })); }; const handleChange = (e: ChangeEvent) => { diff --git a/nym-connect/desktop/src/types/service-provider.ts b/nym-connect/desktop/src/types/service-provider.ts index ed370e2755..21cfee1174 100644 --- a/nym-connect/desktop/src/types/service-provider.ts +++ b/nym-connect/desktop/src/types/service-provider.ts @@ -1,6 +1,6 @@ export interface UserDefinedGateway { isActive: boolean; - gateway?: string; + address?: string; } export interface UserDefinedSPAddress { diff --git a/nym-connect/desktop/src/types/user-data.ts b/nym-connect/desktop/src/types/user-data.ts index 8bd43a941e..db09b32b74 100644 --- a/nym-connect/desktop/src/types/user-data.ts +++ b/nym-connect/desktop/src/types/user-data.ts @@ -1,6 +1,18 @@ export type PrivacyLevel = 'High' | 'Medium'; +export type SelectedGateway = { + address?: string; + is_active?: boolean; +}; + +export type SelectedSp = { + address?: string; + is_active?: boolean; +}; + export type UserData = { monitoring?: boolean; privacy_level?: PrivacyLevel; + selected_gateway?: SelectedGateway; + selected_sp?: SelectedSp; };