rework error alerts
This commit is contained in:
parent
504c0b4156
commit
acc5c71bfa
@ -58,6 +58,7 @@ pub fn run() -> tauri::Result<()> {
|
|||||||
ipc::save_config,
|
ipc::save_config,
|
||||||
ipc::launch_terminal,
|
ipc::launch_terminal,
|
||||||
ipc::get_setup_errors,
|
ipc::get_setup_errors,
|
||||||
|
ipc::exit,
|
||||||
])
|
])
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let res = rt::block_on(setup(app));
|
let res = rt::block_on(setup(app));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use sqlx::types::Uuid;
|
use sqlx::types::Uuid;
|
||||||
use tauri::State;
|
use tauri::{AppHandle, State};
|
||||||
|
|
||||||
use crate::config::AppConfig;
|
use crate::config::AppConfig;
|
||||||
use crate::credentials::{
|
use crate::credentials::{
|
||||||
@ -160,3 +160,9 @@ pub async fn launch_terminal(base: bool) -> Result<(), LaunchTerminalError> {
|
|||||||
pub async fn get_setup_errors(app_state: State<'_, AppState>) -> Result<Vec<String>, ()> {
|
pub async fn get_setup_errors(app_state: State<'_, AppState>) -> Result<Vec<String>, ()> {
|
||||||
Ok(app_state.setup_errors.clone())
|
Ok(app_state.setup_errors.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn exit(app_handle: AppHandle) {
|
||||||
|
app_handle.exit(0)
|
||||||
|
}
|
||||||
|
@ -7,11 +7,34 @@
|
|||||||
export let slideDuration = 150;
|
export let slideDuration = 150;
|
||||||
let animationClass = "";
|
let animationClass = "";
|
||||||
|
|
||||||
export function shake() {
|
let error = null;
|
||||||
|
|
||||||
|
function shake() {
|
||||||
animationClass = 'shake';
|
animationClass = 'shake';
|
||||||
window.setTimeout(() => animationClass = "", 400);
|
window.setTimeout(() => animationClass = "", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function run(fallible) {
|
||||||
|
try {
|
||||||
|
const ret = await Promise.resolve(fallible());
|
||||||
|
error = null;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (error) shake();
|
||||||
|
error = e;
|
||||||
|
// re-throw so it can be caught by the caller if necessary
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a method rather than a prop so that we can re-shake every time
|
||||||
|
// the error occurs, even if the error message doesn't change
|
||||||
|
export function setError(e) {
|
||||||
|
if (error) shake();
|
||||||
|
error = e;
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@ -51,15 +74,17 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<div in:slide="{{duration: slideDuration}}" class="alert alert-error shadow-lg {animationClass} {extraClasses}">
|
{#if error}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
<div transition:slide="{{duration: slideDuration}}" class="alert alert-error shadow-lg {animationClass} {extraClasses}">
|
||||||
<span>
|
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current flex-shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
|
||||||
<slot></slot>
|
<span>
|
||||||
</span>
|
<slot {error}>{error.msg || error}</slot>
|
||||||
|
</span>
|
||||||
|
|
||||||
{#if $$slots.buttons}
|
{#if $$slots.buttons}
|
||||||
<div>
|
<div>
|
||||||
<slot name="buttons"></slot>
|
<slot name="buttons"></slot>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
<input
|
<input
|
||||||
type={show ? 'text' : 'password'}
|
type={show ? 'text' : 'password'}
|
||||||
{value} {placeholder} {autofocus}
|
{value} {placeholder} {autofocus}
|
||||||
|
on:input={e => value = e.target.value}
|
||||||
on:input on:change on:focus on:blur
|
on:input on:change on:focus on:blur
|
||||||
class="input input-bordered flex-grow join-item placeholder:text-gray-500 {classes}"
|
class="input input-bordered flex-grow join-item placeholder:text-gray-500 {classes}"
|
||||||
on:input={e => value = e.target.value}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import { slide } from 'svelte/transition';
|
import { slide } from 'svelte/transition';
|
||||||
import ErrorAlert from '../ErrorAlert.svelte';
|
|
||||||
|
|
||||||
export let title;
|
export let title;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="flex flex-wrap justify-between gap-y-4">
|
<div class="flex flex-wrap justify-between gap-4">
|
||||||
<h3 class="text-lg font-bold shrink-0">{title}</h3>
|
<h3 class="text-lg font-bold shrink-0">{title}</h3>
|
||||||
{#if $$slots.input}
|
{#if $$slots.input}
|
||||||
<slot name="input"></slot>
|
<slot name="input"></slot>
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// Extra 50ms so the window can finish disappearing before the redraw
|
// Extra 50ms so the window can finish disappearing before the redraw
|
||||||
const rehideDelay = Math.min(5000, $appState.config.rehide_ms + 50);
|
const rehideDelay = Math.min(5000, $appState.config.rehide_ms + 50);
|
||||||
|
|
||||||
let error, alert;
|
let alert;
|
||||||
let success = false;
|
let success = false;
|
||||||
async function sendResponse() {
|
async function sendResponse() {
|
||||||
try {
|
try {
|
||||||
@ -20,14 +20,14 @@
|
|||||||
window.setTimeout(cleanupRequest, rehideDelay);
|
window.setTimeout(cleanupRequest, rehideDelay);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (error) {
|
// reset to null so that we go back to asking for approval
|
||||||
alert.shake();
|
$appState.currentRequest.response = null;
|
||||||
}
|
// setTimeout forces this to not happen until the alert has been rendered
|
||||||
error = e;
|
window.setTimeout(() => alert.setError(e), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleResponse() {
|
async function handleResponseCollected() {
|
||||||
if (
|
if (
|
||||||
$appState.sessionStatus === 'unlocked'
|
$appState.sessionStatus === 'unlocked'
|
||||||
|| $appState.currentRequest.response.approval === 'Denied'
|
|| $appState.currentRequest.response.approval === 'Denied'
|
||||||
@ -41,20 +41,17 @@
|
|||||||
{#if success}
|
{#if success}
|
||||||
<!-- if we have successfully sent a response, show it -->
|
<!-- if we have successfully sent a response, show it -->
|
||||||
<ShowResponse />
|
<ShowResponse />
|
||||||
{:else if !$appState.currentRequest?.response || error}
|
{:else if !$appState.currentRequest?.response}
|
||||||
<!-- if there's no response, or if there was an error sending it, ask for response -->
|
<!-- if a response hasn't been collected, ask for it -->
|
||||||
<div class="flex flex-col space-y-4 p-4 m-auto max-w-xl h-screen items-center justify-center">
|
<div class="flex flex-col space-y-4 p-4 m-auto max-w-xl h-screen items-center justify-center">
|
||||||
{#if error}
|
<ErrorAlert bind:this={alert}>
|
||||||
<ErrorAlert bind:this={alert}>
|
<svelte:fragment slot="buttons">
|
||||||
{error.msg}
|
<button class="btn btn-sm btn-alert-error" on:click={cleanupRequest}>Cancel</button>
|
||||||
<svelte:fragment slot="buttons">
|
<button class="btn btn-sm btn-alert-error" on:click={sendResponse}>Retry</button>
|
||||||
<button class="btn btn-sm btn-alert-error" on:click={cleanupRequest}>Cancel</button>
|
</svelte:fragment>
|
||||||
<button class="btn btn-sm btn-alert-error" on:click={sendResponse}>Retry</button>
|
</ErrorAlert>
|
||||||
</svelte:fragment>
|
|
||||||
</ErrorAlert>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<CollectResponse on:response={handleResponse} />
|
<CollectResponse on:response={handleResponseCollected} />
|
||||||
</div>
|
</div>
|
||||||
{:else if $appState.sessionStatus === 'locked'}
|
{:else if $appState.sessionStatus === 'locked'}
|
||||||
<!-- if session is locked and we do have a response, we must be waiting for unlock -->
|
<!-- if session is locked and we do have a response, we must be waiting for unlock -->
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link target="">
|
<Link target={() => invoke('exit')}>
|
||||||
<div class="flex flex-col items-center gap-4 h-full max-w-56 rounded-box p-4 border border-warning hover:bg-base-200 transition-colors">
|
<div class="flex flex-col items-center gap-4 h-full max-w-56 rounded-box p-4 border border-warning hover:bg-base-200 transition-colors">
|
||||||
<Icon name="arrow-right-start-on-rectangle" class="size-12 stroke-1 stroke-warning" />
|
<Icon name="arrow-right-start-on-rectangle" class="size-12 stroke-1 stroke-warning" />
|
||||||
<h3 class="text-lg font-bold">Exit</h3>
|
<h3 class="text-lg font-bold">Exit</h3>
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<h1 slot="title" class="text-2xl font-bold">Credentials</h1>
|
<h1 slot="title" class="text-2xl font-bold">Credentials</h1>
|
||||||
</Nav>
|
</Nav>
|
||||||
|
|
||||||
<div class="max-w-xl mx-auto flex flex-col gap-y-4 justify-center">
|
<div class="max-w-xl mx-auto mb-12 flex flex-col gap-y-4 justify-center">
|
||||||
<div class="divider">
|
<div class="divider">
|
||||||
<h2 class="text-xl font-bold">AWS Access Keys</h2>
|
<h2 class="text-xl font-bold">AWS Access Keys</h2>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
import { appState } from '../lib/state.js';
|
import { appState } from '../lib/state.js';
|
||||||
import Nav from '../ui/Nav.svelte';
|
import Nav from '../ui/Nav.svelte';
|
||||||
import Link from '../ui/Link.svelte';
|
import Link from '../ui/Link.svelte';
|
||||||
import ErrorAlert from '../ui/ErrorAlert.svelte';
|
|
||||||
import SettingsGroup from '../ui/settings/SettingsGroup.svelte';
|
import SettingsGroup from '../ui/settings/SettingsGroup.svelte';
|
||||||
import Keybind from '../ui/settings/Keybind.svelte';
|
import Keybind from '../ui/settings/Keybind.svelte';
|
||||||
import { Setting, ToggleSetting, NumericSetting, FileSetting, TextSetting, TimeSetting } from '../ui/settings';
|
import { Setting, ToggleSetting, NumericSetting, FileSetting, TextSetting, TimeSetting } from '../ui/settings';
|
||||||
@ -21,6 +20,7 @@
|
|||||||
let error = null;
|
let error = null;
|
||||||
async function save() {
|
async function save() {
|
||||||
try {
|
try {
|
||||||
|
throw('wtf');
|
||||||
await invoke('save_config', {config});
|
await invoke('save_config', {config});
|
||||||
$appState.config = await invoke('get_config');
|
$appState.config = await invoke('get_config');
|
||||||
}
|
}
|
||||||
|
@ -17,34 +17,22 @@
|
|||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
let errorMsg = null;
|
|
||||||
let alert;
|
let alert;
|
||||||
let passphrase = '';
|
let passphrase = '';
|
||||||
|
|
||||||
let saving = false;
|
let saving = false;
|
||||||
async function unlock() {
|
async function unlock() {
|
||||||
|
saving = true;
|
||||||
try {
|
try {
|
||||||
saving = true;
|
await alert.run(async () => invoke('unlock', {passphrase}));
|
||||||
let r = await invoke('unlock', {passphrase});
|
|
||||||
$appState.sessionStatus = 'unlocked';
|
$appState.sessionStatus = 'unlocked';
|
||||||
emit('unlocked');
|
emit('unlocked');
|
||||||
dispatch('unlocked');
|
dispatch('unlocked');
|
||||||
}
|
}
|
||||||
catch (e) {
|
finally {
|
||||||
const root = getRootCause(e);
|
|
||||||
if (e.code === 'GetSession' && root.code) {
|
|
||||||
errorMsg = `Error response from AWS (${root.code}): ${root.msg}`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
errorMsg = e.msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the alert already existed, shake it
|
|
||||||
if (alert) {
|
|
||||||
alert.shake();
|
|
||||||
}
|
|
||||||
|
|
||||||
saving = false;
|
saving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -61,9 +49,7 @@
|
|||||||
<label class="space-y-4">
|
<label class="space-y-4">
|
||||||
<h2 class="font-bold text-xl text-center">Please enter your passphrase</h2>
|
<h2 class="font-bold text-xl text-center">Please enter your passphrase</h2>
|
||||||
|
|
||||||
{#if errorMsg}
|
<ErrorAlert bind:this="{alert}" />
|
||||||
<ErrorAlert bind:this="{alert}">{errorMsg}</ErrorAlert>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-autofocus -->
|
<!-- svelte-ignore a11y-autofocus -->
|
||||||
<PassphraseInput autofocus="true" bind:value={passphrase} placeholder="correct horse battery staple" />
|
<PassphraseInput autofocus="true" bind:value={passphrase} placeholder="correct horse battery staple" />
|
||||||
|
@ -25,17 +25,11 @@
|
|||||||
// (sadly we can't use a reactive binding because reasons I guess)
|
// (sadly we can't use a reactive binding because reasons I guess)
|
||||||
defaults.subscribe(d => local.is_default = local.id === d[local.credential.type])
|
defaults.subscribe(d => local.is_default = local.id === d[local.credential.type])
|
||||||
|
|
||||||
let error, alert;
|
let alert;
|
||||||
async function saveCredential() {
|
async function saveCredential() {
|
||||||
try {
|
await invoke('save_credential', {record: local});
|
||||||
await invoke('save_credential', {record: local});
|
dispatch('update');
|
||||||
dispatch('update');
|
showDetails = false;
|
||||||
showDetails = false;
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
if (error) alert.shake();
|
|
||||||
error = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteModal;
|
let deleteModal;
|
||||||
@ -51,14 +45,14 @@
|
|||||||
async function deleteCredential() {
|
async function deleteCredential() {
|
||||||
try {
|
try {
|
||||||
if (!record.isNew) {
|
if (!record.isNew) {
|
||||||
|
|
||||||
await invoke('delete_credential', {id: record.id});
|
await invoke('delete_credential', {id: record.id});
|
||||||
}
|
}
|
||||||
dispatch('update');
|
dispatch('update');
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
if (error) alert.shake();
|
showDetails = true;
|
||||||
error = e;
|
// wait for showDetails to take effect and the alert to be rendered
|
||||||
|
window.setTimeout(() => alert.setError(e), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -95,17 +89,13 @@
|
|||||||
|
|
||||||
|
|
||||||
{#if showDetails}
|
{#if showDetails}
|
||||||
{#if error}
|
|
||||||
<div class="px-6">
|
|
||||||
<ErrorAlert bind:this={alert}>{error}</ErrorAlert>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<form
|
<form
|
||||||
transition:slide|local={{duration: 200}}
|
transition:slide|local={{duration: 200}}
|
||||||
class=" px-6 pb-4 space-y-4"
|
class=" px-6 pb-4 space-y-4"
|
||||||
on:submit|preventDefault={saveCredential}
|
on:submit|preventDefault={() => alert.run(saveCredential)}
|
||||||
>
|
>
|
||||||
|
<ErrorAlert bind:this={alert} />
|
||||||
|
|
||||||
<div class="grid grid-cols-[auto_1fr] items-center gap-4">
|
<div class="grid grid-cols-[auto_1fr] items-center gap-4">
|
||||||
{#if record.isNew}
|
{#if record.isNew}
|
||||||
<span class="justify-self-end">Name</span>
|
<span class="justify-self-end">Name</span>
|
||||||
@ -131,7 +121,7 @@
|
|||||||
|
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<label class="label cursor-pointer justify-self-start space-x-4">
|
<label class="label cursor-pointer justify-self-start space-x-4">
|
||||||
<span class="label-text">Default for type</span>
|
<span class="label-text">Default AWS access key</span>
|
||||||
<input type="checkbox" class="toggle toggle-accent" bind:checked={local.is_default}>
|
<input type="checkbox" class="toggle toggle-accent" bind:checked={local.is_default}>
|
||||||
</label>
|
</label>
|
||||||
{#if isModified}
|
{#if isModified}
|
||||||
|
@ -14,48 +14,68 @@
|
|||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
let alert, saving;
|
let alert;
|
||||||
|
let saving = false;
|
||||||
let passphrase = '';
|
let passphrase = '';
|
||||||
let confirmPassphrase = '';
|
let confirmPassphrase = '';
|
||||||
let error = null;
|
|
||||||
|
|
||||||
function confirm() {
|
// onChange only fires when an input loses focus, so always set the error if not set
|
||||||
|
function onChange() {
|
||||||
|
console.log(`onChange: passphrase=${passphrase}, confirmPassphrase=${confirmPassphrase}`)
|
||||||
if (passphrase !== confirmPassphrase) {
|
if (passphrase !== confirmPassphrase) {
|
||||||
error = 'Passphrases do not match.';
|
alert.setError('Passphrases do not match.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert.setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// onInput fires on every keystroke, so only dismiss the error, don't create it
|
||||||
|
function onInput() {
|
||||||
|
console.log(`onInput: passphrase=${passphrase}, confirmPassphrase=${confirmPassphrase}`)
|
||||||
|
if (passphrase === confirmPassphrase) {
|
||||||
|
alert.setError(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function save() {
|
async function save() {
|
||||||
if (passphrase === '' || passphrase !== confirmPassphrase) {
|
if (passphrase !== confirmPassphrase) {
|
||||||
alert.shake();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (passphrase === '') {
|
||||||
|
alert.setError('Passphrase is empty.')
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
saving = true;
|
saving = true;
|
||||||
try {
|
try {
|
||||||
await invoke('set_passphrase', {passphrase});
|
await alert.run(async () => {
|
||||||
$appState.sessionStatus = 'unlocked';
|
await invoke('set_passphrase', {passphrase})
|
||||||
dispatch('save');
|
throw('something bad happened');
|
||||||
|
$appState.sessionStatus = 'unlocked';
|
||||||
|
dispatch('save');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (e) {
|
finally {
|
||||||
if (error) alert.shake();
|
saving = false;
|
||||||
error = e;
|
|
||||||
}
|
}
|
||||||
saving = false;
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<form class="form-control gap-y-4" on:submit|preventDefault={save}>
|
<form class="form-control gap-y-4" on:submit|preventDefault={save}>
|
||||||
{#if error}
|
<ErrorAlert bind:this={alert} />
|
||||||
<ErrorAlert bind:this={alert}>{error}</ErrorAlert>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<label class="form-control w-full">
|
<label class="form-control w-full">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
<span class="label-text">Passphrase</span>
|
<span class="label-text">Passphrase</span>
|
||||||
</div>
|
</div>
|
||||||
<PassphraseInput bind:value={passphrase} placeholder="correct horse battery staple" />
|
<PassphraseInput
|
||||||
|
bind:value={passphrase}
|
||||||
|
on:input={onInput}
|
||||||
|
placeholder="correct horse battery staple"
|
||||||
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label class="form-control w-full">
|
<label class="form-control w-full">
|
||||||
@ -64,8 +84,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<PassphraseInput
|
<PassphraseInput
|
||||||
bind:value={confirmPassphrase}
|
bind:value={confirmPassphrase}
|
||||||
|
on:input={onInput} on:change={onChange}
|
||||||
placeholder="correct horse battery staple"
|
placeholder="correct horse battery staple"
|
||||||
on:change={confirm}
|
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
@ -78,7 +98,7 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if cancellable}
|
{#if cancellable}
|
||||||
<Link target="Home" hotkey="Escape">
|
<Link target="Settings" hotkey="Escape">
|
||||||
<button type="button" class="btn btn-outline btn-sm w-full">Cancel</button>
|
<button type="button" class="btn btn-outline btn-sm w-full">Cancel</button>
|
||||||
</Link>
|
</Link>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -2,31 +2,28 @@
|
|||||||
import { invoke } from '@tauri-apps/api/core';
|
import { invoke } from '@tauri-apps/api/core';
|
||||||
import { appState } from '../../lib/state.js';
|
import { appState } from '../../lib/state.js';
|
||||||
|
|
||||||
|
import ErrorAlert from '../../ui/ErrorAlert.svelte';
|
||||||
|
|
||||||
let modal, error, alert;
|
|
||||||
|
|
||||||
function reset() {
|
let modal;
|
||||||
try {
|
let alert;
|
||||||
invoke('reset_session');
|
|
||||||
$appState.sessionStatus = 'empty';
|
async function reset() {
|
||||||
}
|
await invoke('reset_session');
|
||||||
catch (e) {
|
$appState.sessionStatus = 'empty';
|
||||||
if (alert) alert.shake();
|
|
||||||
error = e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<button type="button" class="self-end text-sm text-secondary/75 hover:text-secondary hover:underline focus:ring-accent" on:click={modal.showModal()}>
|
<button type="button" class="self-end text-sm text-secondary/75 hover:underline focus:ring-accent" on:click={modal.showModal()}>
|
||||||
Reset passphrase
|
Reset passphrase
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<dialog class="modal" bind:this={modal}>
|
<dialog class="modal" bind:this={modal}>
|
||||||
<div class="modal-box space-y-6">
|
<div class="modal-box space-y-6">
|
||||||
{#if error}
|
<ErrorAlert bind:this={alert} />
|
||||||
<ErrorAlert>{error}</ErrorAlert>
|
|
||||||
{/if}
|
|
||||||
<h3 class="text-lg font-bold">Delete all credentials?</h3>
|
<h3 class="text-lg font-bold">Delete all credentials?</h3>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<p>Credentials are encrypted with your current passphrase and will be lost if the passphrase is reset.</p>
|
<p>Credentials are encrypted with your current passphrase and will be lost if the passphrase is reset.</p>
|
||||||
@ -35,7 +32,9 @@
|
|||||||
<div class="modal-action">
|
<div class="modal-action">
|
||||||
<form method="dialog" class="flex gap-x-4">
|
<form method="dialog" class="flex gap-x-4">
|
||||||
<button autofocus class="btn btn-outline">Cancel</button>
|
<button autofocus class="btn btn-outline">Cancel</button>
|
||||||
<button class="btn btn-error" on:click={reset}>Delete</button>
|
<button class="btn btn-error" on:click|preventDefault={() => alert.run(reset)}>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user