return to previous view after approval flow

This commit is contained in:
Joseph Montanaro 2023-05-01 13:27:28 -07:00
parent 886fcd9bb8
commit a75f34865e
9 changed files with 70 additions and 91 deletions

View File

@ -1,11 +1,13 @@
<script> <script>
import { onMount } from 'svelte';
import { listen } from '@tauri-apps/api/event'; import { listen } from '@tauri-apps/api/event';
import { invoke } from '@tauri-apps/api/tauri'; import { invoke } from '@tauri-apps/api/tauri';
import { appState } from './lib/state.js'; import { appState, acceptRequest } from './lib/state.js';
import { views, currentView, navigate } from './lib/routing.js'; import { views, currentView, navigate } from './lib/routing.js';
$views = import.meta.glob('./views/*.svelte', {eager: true}); $views = import.meta.glob('./views/*.svelte', {eager: true});
navigate('Home'); navigate('Home');
@ -14,6 +16,13 @@ invoke('get_config').then(config => $appState.config = config);
listen('credentials-request', (tauriEvent) => { listen('credentials-request', (tauriEvent) => {
$appState.pendingRequests.put(tauriEvent.payload); $appState.pendingRequests.put(tauriEvent.payload);
}); });
// $appState.pendingRequests.get().then(req => {
// $appState.currentRequest = req;
// })
appState.subscribe($s => window.state = $s);
acceptRequest();
</script> </script>

View File

@ -3,6 +3,7 @@ import { writable, get } from 'svelte/store';
export let views = writable(); export let views = writable();
export let currentView = writable(); export let currentView = writable();
export let previousView = writable();
export function navigate(viewName) { export function navigate(viewName) {
let v = get(views)[`./views/${viewName}.svelte`].default; let v = get(views)[`./views/${viewName}.svelte`].default;

View File

@ -1,9 +1,31 @@
import { writable } from 'svelte/store'; import { writable, get } from 'svelte/store';
import queue from './queue.js'; import queue from './queue.js';
import { navigate, currentView, previousView } from './routing.js';
export let appState = writable({ export let appState = writable({
currentRequest: null, currentRequest: null,
pendingRequests: queue(), pendingRequests: queue(),
credentialStatus: 'locked', credentialStatus: 'locked',
}); });
export async function acceptRequest() {
let req = await get(appState).pendingRequests.get();
appState.update($appState => {
$appState.currentRequest = req;
return $appState;
});
previousView.set(get(currentView));
navigate('Approve');
}
export function completeRequest() {
appState.update($appState => {
$appState.currentRequest = null;
return $appState;
});
currentView.set(get(previousView));
previousView.set(null);
acceptRequest();
}

View File

@ -8,9 +8,10 @@
async function approve() { async function approve() {
$appState.currentRequest.approval = 'Approved';
let status = await invoke('get_session_status'); let status = await invoke('get_session_status');
if (status === 'unlocked') { if (status === 'unlocked') {
navigate('ShowApproved'); navigate('ShowResponse');
} }
else if (status === 'locked') { else if (status === 'locked') {
navigate('Unlock'); navigate('Unlock');
@ -20,9 +21,15 @@
} }
} }
var appName = null; function deny() {
$appState.currentRequest.approval = 'Denied';
navigate('ShowResponse');
}
let appName = null;
if ($appState.currentRequest.clients.length === 1) { if ($appState.currentRequest.clients.length === 1) {
let path = $appState.currentRequest.clients[0].exe; let path = $appState.currentRequest.clients[0].exe;
// grab the filename from the path
let m = path.match(/\/([^/]+?$)|\\([^\\]+?$)/); let m = path.match(/\/([^/]+?$)|\\([^\\]+?$)/);
appName = m[1] || m[2]; appName = m[1] || m[2];
} }
@ -40,7 +47,7 @@
</div> </div>
<div class="grid grid-cols-2"> <div class="grid grid-cols-2">
<Link target="ShowDenied" hotkey="Escape"> <Link target="{deny}" hotkey="Escape">
<button class="btn btn-error justify-self-start"> <button class="btn btn-error justify-self-start">
Deny Deny
<kbd class="ml-2 normal-case px-1 py-0.5 rounded border border-neutral">Esc</kbd> <kbd class="ml-2 normal-case px-1 py-0.5 rounded border border-neutral">Esc</kbd>

View File

@ -29,7 +29,7 @@
try { try {
await invoke('save_credentials', {credentials, passphrase}); await invoke('save_credentials', {credentials, passphrase});
if ($appState.currentRequest) { if ($appState.currentRequest) {
navigate('ShowApproved'); navigate('ShowResponse');
} }
else { else {
navigate('Home'); navigate('Home');

View File

@ -11,12 +11,12 @@
import vaultDoorSvg from '../assets/vault_door.svg?raw'; import vaultDoorSvg from '../assets/vault_door.svg?raw';
onMount(async () => { // onMount(async () => {
// will block until a request comes in // // will block until a request comes in
let req = await $appState.pendingRequests.get(); // let req = await $appState.pendingRequests.get();
$appState.currentRequest = req; // $appState.currentRequest = req;
navigate('Approve'); // navigate('Approve');
}); // });
</script> </script>

View File

@ -1,53 +0,0 @@
<script>
import { onMount } from 'svelte';
import { draw, fade } from 'svelte/transition';
import { invoke } from '@tauri-apps/api/tauri';
import { appState } from '../lib/state.js';
import { navigate } from '../lib/routing.js';
import ErrorAlert from '../ui/ErrorAlert.svelte';
import Icon from '../ui/Icon.svelte';
import Link from '../ui/Link.svelte';
let error = null;
async function respond() {
let response = {
id: $appState.currentRequest.id,
approval: 'Denied',
}
try {
await invoke('respond', {response});
$appState.currentRequest = null;
window.setTimeout(() => navigate('Home'), 1000);
}
catch (e) {
error = e;
}
}
onMount(respond);
</script>
{#if error}
<div class="flex flex-col h-screen items-center justify-center m-auto max-w-lg">
<ErrorAlert>
{error}
<svelte:fragment slot="buttons">
<Link target="Home">
<button class="btn btn-sm btn-alert-error" on:click={() => navigate('Home')}>Ok</button>
</Link>
</svelte:fragment>
</ErrorAlert>
</div>
{:else}
<div class="flex flex-col items-center justify-center h-screen max-w-max m-auto">
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
<path in:draw="{{duration: 500}}" stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<div in:fade="{{delay: 200, duration: 300}}" class="text-2xl font-bold">Denied!</div>
</div>
{/if}

View File

@ -3,10 +3,8 @@
import { draw, fade } from 'svelte/transition'; import { draw, fade } from 'svelte/transition';
import { invoke } from '@tauri-apps/api/tauri'; import { invoke } from '@tauri-apps/api/tauri';
import { appState } from '../lib/state.js'; import { appState, completeRequest } from '../lib/state.js';
import { navigate } from '../lib/routing.js';
import ErrorAlert from '../ui/ErrorAlert.svelte'; import ErrorAlert from '../ui/ErrorAlert.svelte';
import Icon from '../ui/Icon.svelte';
import Link from '../ui/Link.svelte'; import Link from '../ui/Link.svelte';
let success = false; let success = false;
@ -17,19 +15,17 @@
let fadeDelay = drawDuration * 0.4; let fadeDelay = drawDuration * 0.4;
async function respond() { async function respond() {
let response = { let packet = {
id: $appState.currentRequest.id, id: $appState.currentRequest.id,
approval: 'Approved', approval: $appState.currentRequest.approval,
}; };
try { try {
await invoke('respond', {response}); await invoke('respond', {response: packet});
success = true; success = true;
$appState.currentRequest = null;
window.setTimeout( window.setTimeout(
() => navigate('Home'), completeRequest,
// Extra 50ms so the window can finish disappearing before the screen changes // Extra 50ms so the window can finish disappearing before the redraw
Math.min(5000, $appState.config.rehide_ms + 50), Math.min(5000, $appState.config.rehide_ms + 50),
); );
} }
@ -55,21 +51,18 @@
</div> </div>
{:else if success} {:else if success}
<div class="flex flex-col h-screen items-center justify-center max-w-max m-auto"> <div class="flex flex-col h-screen items-center justify-center max-w-max m-auto">
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor"> {#if $appState.currentRequest.approval === 'Approved'}
<path in:draw="{{duration: drawDuration}}" stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> <svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
</svg> <path in:draw="{{duration: drawDuration}}" stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{:else}
<svg xmlns="http://www.w3.org/2000/svg" class="w-36 h-36" fill="none" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor">
<path in:draw="{{duration: 500}}" stroke-linecap="round" stroke-linejoin="round" d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
{/if}
<div in:fade="{{duration: fadeDuration, delay: fadeDelay}}" class="text-2xl font-bold">
<div in:fade="{{duration: fadeDuration, delay: fadeDelay}}" class="text-2xl font-bold">Approved!</div> {$appState.currentRequest.approval}!
</div>
</div> </div>
{/if} {/if}
<!--
{#if error}
<div class="text-red-400">{error}</div>
{:else}
<h1 class="text-4xl text-gray-300">Approved!</h1>
{/if}
-->

View File

@ -24,7 +24,7 @@
let r = await invoke('unlock', {passphrase}); let r = await invoke('unlock', {passphrase});
$appState.credentialStatus = 'unlocked'; $appState.credentialStatus = 'unlocked';
if ($appState.currentRequest) { if ($appState.currentRequest) {
navigate('ShowApproved'); navigate('ShowResponse');
} }
else { else {
navigate('Home'); navigate('Home');