diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-10-11 01:18:18 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-10-11 01:18:18 -0400 |
| commit | 72f3d8c5ab3e2a42cf1a76d0c08815dbe46e50a1 (patch) | |
| tree | 2b582e5319ac377649379851f8f5910517ca2a72 | |
| parent | 2e2e3980ab78052be74f4007c343e69a583648fe (diff) | |
Move login to its own route.
This - in passing - fixes the problem where the client failed to subscribe after logging in, by causing the whole subscription process to be re-run when returning to the main interface.
| -rw-r--r-- | src/ui.rs | 46 | ||||
| -rw-r--r-- | ui/lib/apiServer.js | 2 | ||||
| -rw-r--r-- | ui/lib/components/LogIn.svelte | 4 | ||||
| -rw-r--r-- | ui/lib/components/LogOut.svelte | 8 | ||||
| -rw-r--r-- | ui/lib/components/MessageInput.svelte | 2 | ||||
| -rw-r--r-- | ui/routes/(app)/+layout.svelte | 24 | ||||
| -rw-r--r-- | ui/routes/(login)/login/+page.svelte | 5 |
7 files changed, 63 insertions, 28 deletions
@@ -14,25 +14,45 @@ use crate::{app::App, channel, error::Internal, login::Login}; #[folder = "target/ui"] struct Assets; +impl Assets { + fn load(path: impl AsRef<str>) -> Result<Asset, NotFound<String>> { + let path = path.as_ref(); + let mime = mime_guess::from_path(path).first_or_octet_stream(); + + Self::get(path) + .map(|file| Asset(mime, file)) + .ok_or(NotFound(format!("not found: {path}"))) + } + + fn index() -> Result<Asset, Internal> { + // "not found" in this case really is an internal error, as it should + // never happen. `index.html` is a known-valid path. + Ok(Self::load("index.html")?) + } +} + pub fn router() -> Router<App> { Router::new() .route("/*path", get(asset)) .route("/", get(root)) + .route("/login", get(login)) .route("/ch/:channel", get(channel)) } async fn asset(Path(path): Path<String>) -> Result<Asset, NotFound<String>> { - let mime = mime_guess::from_path(&path).first_or_octet_stream(); + Assets::load(path) +} - Assets::get(&path) - .map(|file| Asset(mime, file)) - .ok_or(NotFound(format!("not found: {path}"))) +async fn root(login: Option<Login>) -> Result<impl IntoResponse, Internal> { + if login.is_none() { + Ok(Redirect::temporary("/login").into_response()) + } else { + Ok(Assets::index()?.into_response()) + } } -async fn root() -> Result<Asset, Internal> { - // "not found" in this case really is an internal error, as it should - // never happen. `index.html` is a known-valid path. - Ok(asset(Path(String::from("index.html"))).await?) +async fn login() -> Result<impl IntoResponse, Internal> { + Assets::index() } async fn channel( @@ -40,13 +60,13 @@ async fn channel( login: Option<Login>, Path(channel): Path<channel::Id>, ) -> Result<impl IntoResponse, Internal> { - Ok(if login.is_none() { - Redirect::temporary("/").into_response() + if login.is_none() { + Ok(Redirect::temporary("/").into_response()) } else if app.channels().get(&channel).await?.is_none() { - NotFound(root().await?).into_response() + Ok(NotFound(Assets::index()?).into_response()) } else { - root().await?.into_response() - }) + Ok(Assets::index()?.into_response()) + } } struct Asset(Mime, EmbeddedFile); diff --git a/ui/lib/apiServer.js b/ui/lib/apiServer.js index 538fa85..ccd6e66 100644 --- a/ui/lib/apiServer.js +++ b/ui/lib/apiServer.js @@ -66,6 +66,8 @@ export function subscribeToEvents(resume_point) { break; } } + + return evtSource; } function onLoginEvent(data) { diff --git a/ui/lib/components/LogIn.svelte b/ui/lib/components/LogIn.svelte index 2836e6d..e1cda8a 100644 --- a/ui/lib/components/LogIn.svelte +++ b/ui/lib/components/LogIn.svelte @@ -1,4 +1,5 @@ <script> + import { goto } from '$app/navigation'; import { logIn } from '$lib/apiServer'; import { currentUser } from '$lib/store'; @@ -6,13 +7,14 @@ let username = ''; let password = ''; - async function handleLogin(event) { + async function handleLogin() { disabled = true; const response = await logIn(username, password); if (200 <= response.status && response.status < 300) { currentUser.update(() => ({ username })); username = ''; password = ''; + goto('/'); } disabled = false; } diff --git a/ui/lib/components/LogOut.svelte b/ui/lib/components/LogOut.svelte index 01bef1b..ba0861a 100644 --- a/ui/lib/components/LogOut.svelte +++ b/ui/lib/components/LogOut.svelte @@ -1,17 +1,21 @@ <script> + import { goto } from '$app/navigation'; import { logOut} from '$lib/apiServer'; import { currentUser } from '$lib/store'; - async function handleLogout(event) { + async function handleLogout() { const response = await logOut(); if (200 <= response.status && response.status < 300) { currentUser.update(() => null); + goto('/login'); } } </script> <form on:submit|preventDefault={handleLogout}> - @{$currentUser.username} + {#if $currentUser} + @{$currentUser.username} + {/if} <button class="border-slate-500 border-solid border-2 font-bold p-1 rounded" type="submit" diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte index 0da78d4..b2746e0 100644 --- a/ui/lib/components/MessageInput.svelte +++ b/ui/lib/components/MessageInput.svelte @@ -4,7 +4,7 @@ export let channel = null; let input; - let value; + let value = ''; let sending = false; $: disabled = (channel === null); diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte index 1d561ae..0f8e83c 100644 --- a/ui/routes/(app)/+layout.svelte +++ b/ui/routes/(app)/+layout.svelte @@ -1,22 +1,19 @@ <script> - import { onMount } from 'svelte'; import { page } from '$app/stores'; + import { goto } from '$app/navigation'; + import { onMount, onDestroy } from 'svelte'; import { boot, subscribeToEvents } from '$lib/apiServer'; import { currentUser, logins, channelsList, messages } from '$lib/store'; import ChannelList from '$lib/components/ChannelList.svelte'; import CreateChannelForm from '$lib/components/CreateChannelForm.svelte'; - import LogIn from '$lib/components/LogIn.svelte'; import MessageInput from '$lib/components/MessageInput.svelte'; - let user; let loading = true; - $: channel = $page?.params?.channel; + let events = null; - currentUser.subscribe((value) => { - user = value; - }); + $: channel = $page?.params?.channel; function onBooted(boot) { currentUser.update(() => ({ @@ -34,10 +31,11 @@ switch (response.status) { case 200: onBooted(response.data); - subscribeToEvents(response.data.resume_point); + events = subscribeToEvents(response.data.resume_point); break; case 401: currentUser.update(() => null); + goto('/login'); break; default: // TODO: display error. @@ -48,11 +46,17 @@ } loading = false; }); + + onDestroy(async () => { + if (events !== null) { + events.close(); + } + }); </script> {#if loading} <h2>Loading…</h2> -{:else if user != null} +{:else} <div id="interface"> <div class="channel-list"> <ChannelList active={channel} /> @@ -67,8 +71,6 @@ <MessageInput {channel} /> </div> </div> -{:else} - <LogIn /> {/if} <style> diff --git a/ui/routes/(login)/login/+page.svelte b/ui/routes/(login)/login/+page.svelte new file mode 100644 index 0000000..c333fdd --- /dev/null +++ b/ui/routes/(login)/login/+page.svelte @@ -0,0 +1,5 @@ +<script> + import LogIn from '$lib/components/LogIn.svelte'; +</script> + +<LogIn /> |
