victor HF staff julien-c HF staff Adrien Denat commited on
Commit
fe2328e
1 Parent(s): a11cd21

Toast errors (#91)

Browse files

Co-authored-by: Julien Chaumond <[email protected]>
Co-authored-by: Adrien Denat <[email protected]>

src/lib/components/Toast.svelte ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { fade } from "svelte/transition";
3
+
4
+ import IconDazzled from "$lib/components/icons/IconDazzled.svelte";
5
+
6
+ export let message = "";
7
+ </script>
8
+
9
+ <div
10
+ transition:fade={{ duration: 300 }}
11
+ class="fixed right-0 top-12 md:top-0 bg-gradient-to-bl from-red-500/20 via-red-500/0 to-red-500/0 pt-2 md:pt-5 pr-2 md:pr-8 pl-36 pb-36 z-20 pointer-events-none"
12
+ >
13
+ <div
14
+ class="flex items-center bg-white/90 dark:bg-gray-900/80 rounded-full py-1 px-3 shadow-sm pointer-events-auto"
15
+ >
16
+ <IconDazzled classNames="text-2xl mr-2" />
17
+ <h2 class="font-semibold">{message}</h2>
18
+ </div>
19
+ </div>
src/lib/components/icons/IconDazzled.svelte ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ export let classNames = "";
3
+ </script>
4
+
5
+ <svg
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ width="1em"
8
+ height="1em"
9
+ class={classNames}
10
+ fill="none"
11
+ viewBox="0 0 26 23"
12
+ >
13
+ <path
14
+ fill="url(#a)"
15
+ d="M.93 10.65A10.17 10.17 0 0 1 11.11.48h4.67a9.45 9.45 0 0 1 0 18.89H4.53L1.62 22.2a.38.38 0 0 1-.69-.28V10.65Z"
16
+ />
17
+ <path
18
+ fill="#000"
19
+ fill-rule="evenodd"
20
+ d="M11.52 7.4a1.86 1.86 0 1 1-3.72 0 1.86 1.86 0 0 1 3.72 0Zm7.57 0a1.86 1.86 0 1 1-3.73 0 1.86 1.86 0 0 1 3.73 0ZM8.9 12.9a.55.55 0 0 0-.11.35.76.76 0 0 1-1.51 0c0-.95.67-1.94 1.76-1.94 1.09 0 1.76 1 1.76 1.94H9.3a.55.55 0 0 0-.12-.35c-.06-.07-.1-.08-.13-.08s-.08 0-.14.08Zm4.04 0a.55.55 0 0 0-.12.35h-1.51c0-.95.68-1.94 1.76-1.94 1.1 0 1.77 1 1.77 1.94h-1.51a.55.55 0 0 0-.12-.35c-.06-.07-.11-.08-.14-.08-.02 0-.07 0-.13.08Zm-1.89.79c-.02 0-.07-.01-.13-.08a.55.55 0 0 1-.12-.36h-1.5c0 .95.67 1.95 1.75 1.95 1.1 0 1.77-1 1.77-1.95h-1.51c0 .16-.06.28-.12.36-.06.07-.11.08-.14.08Zm4.04 0c-.03 0-.08-.01-.14-.08a.55.55 0 0 1-.12-.36h-1.5c0 .95.67 1.95 1.76 1.95 1.08 0 1.76-1 1.76-1.95h-1.51c0 .16-.06.28-.12.36-.06.07-.11.08-.13.08Zm1.76-.44c0-.16.05-.28.12-.35.06-.07.1-.08.13-.08s.08 0 .14.08c.06.07.11.2.11.35a.76.76 0 0 0 1.51 0c0-.95-.67-1.94-1.76-1.94-1.09 0-1.76 1-1.76 1.94h1.5Z"
21
+ clip-rule="evenodd"
22
+ />
23
+ <defs>
24
+ <radialGradient
25
+ id="a"
26
+ cx="0"
27
+ cy="0"
28
+ r="1"
29
+ gradientTransform="matrix(0 31.37 -34.85 0 13.08 -9.02)"
30
+ gradientUnits="userSpaceOnUse"
31
+ >
32
+ <stop stop-color="#FFD21E" />
33
+ <stop offset="1" stop-color="red" />
34
+ </radialGradient>
35
+ </defs>
36
+ </svg>
src/lib/shareConversation.ts CHANGED
@@ -1,4 +1,5 @@
1
  import { base } from "$app/paths";
 
2
 
3
  export async function shareConversation(id: string, title: string) {
4
  try {
@@ -10,7 +11,8 @@ export async function shareConversation(id: string, title: string) {
10
  });
11
 
12
  if (!res.ok) {
13
- alert("Error while sharing conversation: " + (await res.text()));
 
14
  return;
15
  }
16
 
@@ -26,7 +28,7 @@ export async function shareConversation(id: string, title: string) {
26
  prompt("Copy this public url to share:", url);
27
  }
28
  } catch (err) {
 
29
  console.error(err);
30
- alert(String(err));
31
  }
32
  }
 
1
  import { base } from "$app/paths";
2
+ import { ERROR_MESSAGES, error } from "$lib/stores/errors";
3
 
4
  export async function shareConversation(id: string, title: string) {
5
  try {
 
11
  });
12
 
13
  if (!res.ok) {
14
+ error.set("Error while sharing conversation, try again.");
15
+ console.error("Error while sharing conversation: " + (await res.text()));
16
  return;
17
  }
18
 
 
28
  prompt("Copy this public url to share:", url);
29
  }
30
  } catch (err) {
31
+ error.set(ERROR_MESSAGES.default);
32
  console.error(err);
 
33
  }
34
  }
src/lib/stores/errors.ts ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import { writable } from "svelte/store";
2
+
3
+ export const ERROR_MESSAGES = {
4
+ default: "Oops, something went wrong.",
5
+ };
6
+
7
+ export const error = writable<string | null>(null);
src/routes/+layout.svelte CHANGED
@@ -1,19 +1,41 @@
1
  <script lang="ts">
 
2
  import { goto, invalidate } from "$app/navigation";
3
  import { page } from "$app/stores";
4
  import "../styles/main.css";
5
  import type { LayoutData } from "./$types";
6
  import { base } from "$app/paths";
 
 
7
  import { shareConversation } from "$lib/shareConversation";
8
  import { UrlDependency } from "$lib/types/UrlDependency";
 
9
 
10
  import MobileNav from "$lib/components/MobileNav.svelte";
11
  import NavMenu from "$lib/components/NavMenu.svelte";
12
- import { PUBLIC_ORIGIN } from "$env/static/public";
13
 
14
  export let data: LayoutData;
15
 
16
  let isNavOpen = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  async function deleteConversation(id: string) {
19
  try {
@@ -25,7 +47,7 @@
25
  });
26
 
27
  if (!res.ok) {
28
- alert("Error while deleting conversation: " + (await res.text()));
29
  return;
30
  }
31
 
@@ -36,9 +58,15 @@
36
  }
37
  } catch (err) {
38
  console.error(err);
39
- alert(String(err));
40
  }
41
  }
 
 
 
 
 
 
42
  </script>
43
 
44
  <svelte:head>
@@ -70,5 +98,8 @@
70
  on:deleteConversation={(ev) => deleteConversation(ev.detail)}
71
  />
72
  </nav>
 
 
 
73
  <slot />
74
  </div>
 
1
  <script lang="ts">
2
+ import { onDestroy } from "svelte";
3
  import { goto, invalidate } from "$app/navigation";
4
  import { page } from "$app/stores";
5
  import "../styles/main.css";
6
  import type { LayoutData } from "./$types";
7
  import { base } from "$app/paths";
8
+ import { PUBLIC_ORIGIN } from "$env/static/public";
9
+
10
  import { shareConversation } from "$lib/shareConversation";
11
  import { UrlDependency } from "$lib/types/UrlDependency";
12
+ import { error } from "$lib/stores/errors";
13
 
14
  import MobileNav from "$lib/components/MobileNav.svelte";
15
  import NavMenu from "$lib/components/NavMenu.svelte";
16
+ import Toast from "$lib/components/Toast.svelte";
17
 
18
  export let data: LayoutData;
19
 
20
  let isNavOpen = false;
21
+ let errorToastTimeout: NodeJS.Timeout;
22
+ let currentError: string | null;
23
+
24
+ async function onError() {
25
+ // If a new different error comes, wait for the current error to hide first
26
+ if ($error && currentError && $error !== currentError) {
27
+ clearTimeout(errorToastTimeout);
28
+ currentError = null;
29
+ await new Promise((resolve) => setTimeout(resolve, 300));
30
+ }
31
+
32
+ currentError = $error;
33
+
34
+ errorToastTimeout = setTimeout(() => {
35
+ $error = null;
36
+ currentError = null;
37
+ }, 3000);
38
+ }
39
 
40
  async function deleteConversation(id: string) {
41
  try {
 
47
  });
48
 
49
  if (!res.ok) {
50
+ $error = "Error while deleting conversation, try again.";
51
  return;
52
  }
53
 
 
58
  }
59
  } catch (err) {
60
  console.error(err);
61
+ $error = String(err);
62
  }
63
  }
64
+
65
+ onDestroy(() => {
66
+ clearTimeout(errorToastTimeout);
67
+ });
68
+
69
+ $: if ($error) onError();
70
  </script>
71
 
72
  <svelte:head>
 
98
  on:deleteConversation={(ev) => deleteConversation(ev.detail)}
99
  />
100
  </nav>
101
+ {#if currentError}
102
+ <Toast message={currentError} />
103
+ {/if}
104
  <slot />
105
  </div>
src/routes/+page.svelte CHANGED
@@ -1,8 +1,9 @@
1
  <script lang="ts">
2
- import { goto } from '$app/navigation';
3
- import { base } from '$app/paths';
4
- import ChatWindow from '$lib/components/chat/ChatWindow.svelte';
5
- import { pendingMessage } from '$lib/stores/pendingMessage';
 
6
 
7
  let loading = false;
8
 
@@ -17,7 +18,8 @@
17
  });
18
 
19
  if (!res.ok) {
20
- alert('Error while creating conversation: ' + (await res.text()));
 
21
  return;
22
  }
23
 
@@ -29,7 +31,8 @@
29
  // invalidateAll to update list of conversations
30
  await goto(`${base}/conversation/${conversationId}`, { invalidateAll: true });
31
  } catch (err) {
32
- alert(String(err));
 
33
  } finally {
34
  loading = false;
35
  }
 
1
  <script lang="ts">
2
+ import { goto } from "$app/navigation";
3
+ import { base } from "$app/paths";
4
+ import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
5
+ import { ERROR_MESSAGES, error } from "$lib/stores/errors";
6
+ import { pendingMessage } from "$lib/stores/pendingMessage";
7
 
8
  let loading = false;
9
 
 
18
  });
19
 
20
  if (!res.ok) {
21
+ error.set("Error while creating conversation, try again.");
22
+ console.error("Error while creating conversation: " + (await res.text()));
23
  return;
24
  }
25
 
 
31
  // invalidateAll to update list of conversations
32
  await goto(`${base}/conversation/${conversationId}`, { invalidateAll: true });
33
  } catch (err) {
34
+ error.set(ERROR_MESSAGES.default);
35
+ console.error(err);
36
  } finally {
37
  loading = false;
38
  }
src/routes/conversation/[id]/+page.svelte CHANGED
@@ -10,6 +10,7 @@
10
  import { PUBLIC_MAX_INPUT_TOKENS } from "$env/static/public";
11
  import { shareConversation } from "$lib/shareConversation";
12
  import { UrlDependency } from "$lib/types/UrlDependency";
 
13
 
14
  export let data: PageData;
15
 
@@ -105,8 +106,9 @@
105
  await invalidate(UrlDependency.ConversationList);
106
  }
107
  } catch (err) {
 
 
108
  console.error(err);
109
- alert(String(err));
110
  } finally {
111
  loading = false;
112
  }
 
10
  import { PUBLIC_MAX_INPUT_TOKENS } from "$env/static/public";
11
  import { shareConversation } from "$lib/shareConversation";
12
  import { UrlDependency } from "$lib/types/UrlDependency";
13
+ import { error } from "$lib/stores/errors";
14
 
15
  export let data: PageData;
16
 
 
106
  await invalidate(UrlDependency.ConversationList);
107
  }
108
  } catch (err) {
109
+ // TODO: Should prob check if this is really a TooManyRequests error
110
+ $error = "Too much traffic, please try again.";
111
  console.error(err);
 
112
  } finally {
113
  loading = false;
114
  }
src/routes/r/[id]/+page.svelte CHANGED
@@ -3,6 +3,7 @@
3
  import { base } from "$app/paths";
4
  import { page } from "$app/stores";
5
  import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
 
6
  import { pendingMessage } from "$lib/stores/pendingMessage";
7
  import type { PageData } from "./$types";
8
 
@@ -24,7 +25,8 @@
24
  });
25
 
26
  if (!res.ok) {
27
- alert("Error while creating conversation: " + (await res.text()));
 
28
  return;
29
  }
30
 
@@ -36,7 +38,8 @@
36
  // invalidateAll to update list of conversations
37
  await goto(`${base}/conversation/${conversationId}`, { invalidateAll: true });
38
  } catch (err) {
39
- alert(String(err));
 
40
  } finally {
41
  loading = false;
42
  }
 
3
  import { base } from "$app/paths";
4
  import { page } from "$app/stores";
5
  import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
6
+ import { ERROR_MESSAGES, error } from "$lib/stores/errors";
7
  import { pendingMessage } from "$lib/stores/pendingMessage";
8
  import type { PageData } from "./$types";
9
 
 
25
  });
26
 
27
  if (!res.ok) {
28
+ error.set("Error while creating conversation, try again.");
29
+ console.error("Error while creating conversation: " + (await res.text()));
30
  return;
31
  }
32
 
 
38
  // invalidateAll to update list of conversations
39
  await goto(`${base}/conversation/${conversationId}`, { invalidateAll: true });
40
  } catch (err) {
41
+ error.set(ERROR_MESSAGES.default);
42
+ console.error(String(err));
43
  } finally {
44
  loading = false;
45
  }