feat(nc-desktop): use userdata storage to save user gateway&sp

This commit is contained in:
pierre
2023-08-01 11:57:57 +02:00
parent 0951c83ace
commit 3317804a80
12 changed files with 102 additions and 28 deletions
+1 -1
View File
@@ -115,4 +115,4 @@
"webpack-merge": "^5.8.0",
"yaml-loader": "^0.8.0"
}
}
}
@@ -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";
@@ -14,6 +14,18 @@ pub enum PrivacyLevel {
Medium,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct SelectedGateway {
address: Option<String>,
is_active: Option<bool>,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct SelectedSp {
address: Option<String>,
is_active: Option<bool>,
}
// 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<bool>,
pub privacy_level: Option<PrivacyLevel>,
pub selected_gateway: Option<SelectedGateway>,
pub selected_sp: Option<SelectedSp>,
}
fn create_directory_path() -> Result<()> {
@@ -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,
@@ -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<SelectedGateway>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<()> {
let mut guard = state.write().await;
guard.set_user_selected_gateway(gateway)
}
#[tauri::command]
pub async fn set_selected_sp(
service_provider: Option<SelectedSp>,
state: tauri::State<'_, Arc<RwLock<State>>>,
) -> Result<()> {
let mut guard = state.write().await;
guard.set_user_selected_sp(service_provider)
}
@@ -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<SelectedGateway>) -> 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<SelectedSp>) -> 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
}
@@ -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 }));
}
};
+29 -19
View File
@@ -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<UserDefinedGateway>({
isActive: false,
gateway: undefined,
address: undefined,
});
const [userDefinedSPAddress, setUserDefinedSPAddress] = useState<UserDefinedSPAddress>({
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<ServiceProvider[]>('get_services');
const fetchedGateways = await invoke<Gateway[]>('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);
}
@@ -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,
@@ -7,7 +7,7 @@ import { AppVersion } from 'src/components/AppVersion';
export const GatewaySettings = () => {
const { userDefinedGateway, setUserDefinedGateway, connectionStatus } = useClientContext();
const [gatewayKey, setGatewayKey] = useState<string | undefined>(userDefinedGateway?.gateway);
const [gatewayKey, setGatewayKey] = useState<string | undefined>(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<HTMLInputElement>) => {
@@ -1,6 +1,6 @@
export interface UserDefinedGateway {
isActive: boolean;
gateway?: string;
address?: string;
}
export interface UserDefinedSPAddress {
@@ -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;
};