feat(gui, tauri): Save settings in Tauri storage (#102)

- Implemented dual persistence strategy:
  - **User Settings**: Persisted across app restarts using `tauri-plugin-store`.
  - **Transient State**: Persisted across page reloads using `sessionStorage`.
- Added `settingsSlice` reducer for managing persistent user settings.
- Updated Redux store configuration to handle multiple persistence layers.
- Added a new Settings page in the GUI where users can specify custom Electrum RPC URLs for Bitcoin and Monero node URLs.
  - Users can input their preferred Electrum server (`ssl://host:port`) and Monero daemon (`http://host:port`).
  - Input fields include validation to ensure correct URL formats.
  - Settings persist across application restarts using Tauri's storage plugin.
  - A reset option is available to revert to default settings.
- Improved the Daemon Controller in the Help page:
  - Renamed `RpcControlBox` to `DaemonControlBox` for clarity.
  - Users can now start the daemon manually if it isn't running or has failed.
  - Added a "Restart GUI" button to apply new settings immediately.
  - Displayed the daemon's status within the controller.
- Upgraded Tauri and related plugins to stable version `2.0.0`:
  - Updated `tauri`, `tauri-build`, and `tauri-utils` to `2.0.0`.
  - Ensured compatibility with the latest stable release.
- Updated Tauri plugins to version `2.0.0`:
  - `tauri-plugin-clipboard-manager`
  - `tauri-plugin-shell`
  - Added new plugins:
    - `tauri-plugin-store` for settings persistence.
    - `tauri-plugin-process` to enable application relaunch.
- Deferred Context initialization until explicitly triggered from the frontend.
  - Moved Context setup from the `setup` function to a new `initialize_context` Tauri command.
  - Allows the application to start without immediately initializing the backend context.
  - Context initialization now considers user-provided settings for Electrum and Monero nodes.
- Introduced a `ValidatedTextField` component for form inputs with validation logic.
  - Provides immediate feedback on input validity.
  - Used in the Settings page for Electrum and Monero node URLs.
- If the user provides an override Monero remote daemon, we check if it reachable and on the correct network before starting the `monero-wallet-rpc`
- Changed `bitcoin_confirmation_target` type from `usize` to `u16`.
This commit is contained in:
binarybaron 2024-10-08 16:57:01 +06:00 committed by GitHub
parent d4503a6e9c
commit 253e0b0cf6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 1124 additions and 451 deletions

View file

@ -64,7 +64,7 @@ export default function SwapDialog({
) : (
<>
<SwapStatePage state={swap.state} />
<SwapStateStepper state={swap.state}/>
<SwapStateStepper state={swap.state} />
</>
)}
</DialogContent>

View file

@ -15,12 +15,12 @@ type PathStep = [type: PathType, step: number, isError: boolean];
* @param latestState - The latest state of the swap process
* @returns A tuple containing [PathType, activeStep, errorFlag]
*/
function getActiveStep(
state: SwapState | null
): PathStep {
function getActiveStep(state: SwapState | null): PathStep {
// In case we cannot infer a correct step from the state
function fallbackStep(reason: string) {
console.error(`Unable to choose correct stepper type (reason: ${reason}, state: ${JSON.stringify(state)}`);
console.error(
`Unable to choose correct stepper type (reason: ${reason}, state: ${JSON.stringify(state)}`,
);
return [PathType.HAPPY_PATH, 0, true] as PathStep;
}
@ -36,12 +36,16 @@ function getActiveStep(
// If the swap is released but we do not have a previous state we fallback
if (latestState === null) {
return fallbackStep("Swap has been released but we do not have a previous state saved to display");
return fallbackStep(
"Swap has been released but we do not have a previous state saved to display",
);
}
// This should really never happen. For this statement to be true, the host has to submit a "Released" event twice
if(latestState.type === "Released") {
return fallbackStep("Both the current and previous states are both of type 'Released'.");
if (latestState.type === "Released") {
return fallbackStep(
"Both the current and previous states are both of type 'Released'.",
);
}
switch (latestState.type) {
@ -111,8 +115,8 @@ function getActiveStep(
return [PathType.UNHAPPY_PATH, 1, true];
default:
return fallbackStep("No step is assigned to the current state");
// TODO: Make this guard work. It should force the compiler to check if we have covered all possible cases.
// return exhaustiveGuard(latestState.type);
// TODO: Make this guard work. It should force the compiler to check if we have covered all possible cases.
// return exhaustiveGuard(latestState.type);
}
}
@ -158,7 +162,7 @@ const UNHAPPY_PATH_STEP_LABELS = [
export default function SwapStateStepper({
state,
}: {
state: SwapState | null
state: SwapState | null;
}) {
const [pathType, activeStep, error] = getActiveStep(state);

View file

@ -18,11 +18,7 @@ import InitiatedPage from "./init/InitiatedPage";
import InitPage from "./init/InitPage";
import WaitingForBitcoinDepositPage from "./init/WaitingForBitcoinDepositPage";
export default function SwapStatePage({
state,
}: {
state: SwapState | null
}) {
export default function SwapStatePage({ state }: { state: SwapState | null }) {
// TODO: Reimplement this using tauri events
/*
const isSyncingMoneroWallet = useAppSelector(