add ui zoom level setting
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="text-[14px]">
|
||||
<html lang="en" class="text-[12px]">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
|
||||
@@ -78,6 +78,28 @@ pub async fn set_ui_theme(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(data_state))]
|
||||
#[tauri::command]
|
||||
pub async fn set_root_font_size(
|
||||
data_state: State<'_, SharedAppData>,
|
||||
size: u32,
|
||||
) -> Result<(), CmdError> {
|
||||
debug!("set_root_font_size");
|
||||
|
||||
let mut app_data_store = data_state.lock().await;
|
||||
let mut app_data = app_data_store
|
||||
.read()
|
||||
.await
|
||||
.map_err(|e| CmdError::new(CmdErrorSource::InternalError, e.to_string()))?;
|
||||
app_data.ui_root_font_size = Some(size);
|
||||
app_data_store.data = app_data;
|
||||
app_data_store
|
||||
.write()
|
||||
.await
|
||||
.map_err(|e| CmdError::new(CmdErrorSource::InternalError, e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip(data_state))]
|
||||
#[tauri::command]
|
||||
pub async fn set_entry_location_selector(
|
||||
|
||||
@@ -19,6 +19,7 @@ pub struct AppData {
|
||||
pub killswitch: Option<bool>,
|
||||
pub entry_location_selector: Option<bool>,
|
||||
pub ui_theme: Option<UiTheme>,
|
||||
pub ui_root_font_size: Option<u32>,
|
||||
pub vpn_mode: Option<VpnMode>,
|
||||
pub entry_node: Option<NodeConfig>,
|
||||
pub exit_node: Option<NodeConfig>,
|
||||
|
||||
@@ -109,6 +109,7 @@ async fn main() -> Result<()> {
|
||||
app_data::set_ui_theme,
|
||||
app_data::set_entry_location_selector,
|
||||
app_data::get_node_countries,
|
||||
app_data::set_root_font_size,
|
||||
node_location::set_node_location,
|
||||
node_location::get_default_node_location,
|
||||
])
|
||||
|
||||
@@ -9,3 +9,5 @@ export const AppName = 'NymVPN';
|
||||
export const ConnectionEvent = 'connection-state';
|
||||
export const ProgressEvent = 'connection-progress';
|
||||
export const QuickConnectPrefix = 'Fastest';
|
||||
// TODO ⚠ keep this value in sync with the one declared in `index.html`
|
||||
export const DefaultRootFontSize = 12; // in px
|
||||
|
||||
@@ -65,6 +65,10 @@ export function mockTauriIPC() {
|
||||
);
|
||||
}
|
||||
|
||||
if (cmd === 'set_root_font_size') {
|
||||
return new Promise<void>((resolve) => resolve());
|
||||
}
|
||||
|
||||
if (cmd === 'get_app_data') {
|
||||
return new Promise<AppDataFromBackend>((resolve) =>
|
||||
resolve({
|
||||
@@ -73,6 +77,7 @@ export function mockTauriIPC() {
|
||||
killswitch: false,
|
||||
entry_location_selector: false,
|
||||
ui_theme: 'Dark',
|
||||
ui_root_font_size: 12,
|
||||
vpn_mode: 'TwoHop',
|
||||
entry_node: {
|
||||
country: {
|
||||
|
||||
@@ -90,7 +90,9 @@ function Home() {
|
||||
</div>
|
||||
<Button
|
||||
className={clsx([
|
||||
'rounded-lg text-lg font-bold py-4 px-6 h-16 focus:outline-none focus:ring-4 focus:ring-black focus:dark:ring-white shadow',
|
||||
'flex justify-center items-center',
|
||||
'rounded-lg text-lg font-bold py-4 px-6 h-16',
|
||||
'focus:outline-none focus:ring-4 focus:ring-black focus:dark:ring-white shadow',
|
||||
(state === 'Disconnected' || state === 'Connecting') &&
|
||||
'bg-melon text-white dark:text-baltic-sea',
|
||||
(state === 'Connected' || state === 'Disconnecting') &&
|
||||
|
||||
@@ -46,7 +46,7 @@ export default function HopSelect({
|
||||
/>
|
||||
<div className="text-base">{country.name}</div>
|
||||
</div>
|
||||
<span className="font-icon scale-150 pointer-events-none">
|
||||
<span className="font-icon text-2xl pointer-events-none">
|
||||
arrow_right
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { invoke } from '@tauri-apps/api';
|
||||
import { Switch } from '@headlessui/react';
|
||||
import { useMainDispatch, useMainState } from '../../contexts';
|
||||
import { StateDispatch } from '../../types';
|
||||
import UiScaler from './UiScaler';
|
||||
|
||||
function Settings() {
|
||||
const state = useMainState();
|
||||
@@ -55,6 +56,7 @@ function Settings() {
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
<UiScaler />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { ChangeEvent, useEffect, useState } from 'react';
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import { useMainDispatch, useMainState } from '../../contexts';
|
||||
import { CmdError, StateDispatch } from '../../types';
|
||||
|
||||
function UiScaler() {
|
||||
const [slideValue, setSlideValue] = useState(12);
|
||||
const dispatch = useMainDispatch() as StateDispatch;
|
||||
const { rootFontSize } = useMainState();
|
||||
|
||||
useEffect(() => {
|
||||
setSlideValue(rootFontSize);
|
||||
}, [rootFontSize]);
|
||||
|
||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSlideValue(parseInt(e.target.value));
|
||||
dispatch({ type: 'set-root-font-size', size: slideValue });
|
||||
};
|
||||
|
||||
const setNewFontSize = () => {
|
||||
document.documentElement.style.fontSize = `${slideValue}px`;
|
||||
dispatch({ type: 'set-root-font-size', size: slideValue });
|
||||
invoke('set_root_font_size', { size: slideValue }).catch((e: CmdError) => {
|
||||
console.warn(`backend error: ${e.source} - ${e.message}`);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-row justify-between items-center gap-10">
|
||||
<p className="text-lg text-baltic-sea dark:text-mercury-pinkish flex-nowrap">
|
||||
{`Zoom level: ${slideValue}`}
|
||||
</p>
|
||||
<input
|
||||
type="range"
|
||||
min="8"
|
||||
max="20"
|
||||
value={slideValue}
|
||||
onChange={handleChange}
|
||||
onMouseUp={setNewFontSize}
|
||||
onKeyUp={setNewFontSize}
|
||||
className="range flex flex-1 accent-melon"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default UiScaler;
|
||||
@@ -26,7 +26,8 @@ export type StateAction =
|
||||
| { type: 'set-ui-theme'; theme: UiTheme }
|
||||
| { type: 'set-countries'; countries: Country[] }
|
||||
| { type: 'set-node-location'; payload: { hop: NodeHop; country: Country } }
|
||||
| { type: 'set-default-node-location'; country: Country };
|
||||
| { type: 'set-default-node-location'; country: Country }
|
||||
| { type: 'set-root-font-size'; size: number };
|
||||
|
||||
export const initialState: AppState = {
|
||||
state: 'Disconnected',
|
||||
@@ -43,6 +44,7 @@ export const initialState: AppState = {
|
||||
code: 'FR',
|
||||
},
|
||||
countries: [],
|
||||
rootFontSize: 12,
|
||||
};
|
||||
|
||||
export function reducer(state: AppState, action: StateAction): AppState {
|
||||
@@ -145,6 +147,11 @@ export function reducer(state: AppState, action: StateAction): AppState {
|
||||
...state,
|
||||
defaultNodeLocation: action.country,
|
||||
};
|
||||
case 'set-root-font-size':
|
||||
return {
|
||||
...state,
|
||||
rootFontSize: action.size,
|
||||
};
|
||||
case 'reset':
|
||||
return initialState;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
ConnectionState,
|
||||
Country,
|
||||
} from '../types';
|
||||
import { DefaultRootFontSize } from '../constants';
|
||||
import { initialState, reducer } from './main';
|
||||
import { useTauriEvents } from './useTauriEvents';
|
||||
|
||||
@@ -89,10 +90,16 @@ export function MainStateProvider({ children }: Props) {
|
||||
.then((data) => {
|
||||
console.log('app data read from disk:');
|
||||
console.log(data);
|
||||
|
||||
if (data.ui_root_font_size) {
|
||||
document.documentElement.style.fontSize = `${data.ui_root_font_size}px`;
|
||||
}
|
||||
|
||||
const partialState: Partial<typeof initialState> = {
|
||||
entrySelector: data.entry_location_selector || false,
|
||||
uiTheme: data.ui_theme || 'Light',
|
||||
vpnMode: data.vpn_mode || 'TwoHop',
|
||||
rootFontSize: data.ui_root_font_size || DefaultRootFontSize,
|
||||
};
|
||||
if (data.entry_node_location) {
|
||||
partialState.entryNodeLocation = data.entry_node_location;
|
||||
|
||||
@@ -19,6 +19,7 @@ export interface AppDataFromBackend {
|
||||
killswitch: boolean | null;
|
||||
entry_location_selector: boolean | null;
|
||||
ui_theme: UiTheme | null;
|
||||
ui_root_font_size: number | null;
|
||||
vpn_mode: VpnMode | null;
|
||||
entry_node: NodeConfig | null;
|
||||
exit_node: NodeConfig | null;
|
||||
|
||||
@@ -31,6 +31,7 @@ export type AppState = {
|
||||
exitNodeLocation: Country | null;
|
||||
defaultNodeLocation: Country;
|
||||
countries: Country[];
|
||||
rootFontSize: number;
|
||||
};
|
||||
|
||||
export type ConnectionEventPayload = {
|
||||
|
||||
Reference in New Issue
Block a user