nsarrazin HF staff commited on
Commit
482a094
1 Parent(s): 264c8d0

Small UX updates assistants (#872)

Browse files
src/lib/stores/settings.ts CHANGED
@@ -17,8 +17,12 @@ type SettingsStore = {
17
  assistants: Array<ObjectId | string>;
18
  };
19
 
 
 
 
 
20
  export function useSettingsStore() {
21
- return getContext<Writable<SettingsStore>>("settings");
22
  }
23
 
24
  export function createSettingsStore(initialValue: Omit<SettingsStore, "recentlySaved">) {
@@ -64,14 +68,35 @@ export function createSettingsStore(initialValue: Omit<SettingsStore, "recentlyS
64
  // debounce server calls by 300ms
65
  }
66
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  const newStore = {
69
  subscribe: baseStore.subscribe,
70
  set: setSettings,
 
71
  update: (fn: (s: SettingsStore) => SettingsStore) => {
72
  setSettings(fn(get(baseStore)));
73
  },
74
- } satisfies Writable<SettingsStore>;
75
 
76
  setContext("settings", newStore);
77
 
 
17
  assistants: Array<ObjectId | string>;
18
  };
19
 
20
+ type SettingsStoreWritable = Writable<SettingsStore> & {
21
+ instantSet: (settings: Partial<SettingsStore>) => Promise<void>;
22
+ };
23
+
24
  export function useSettingsStore() {
25
+ return getContext<SettingsStoreWritable>("settings");
26
  }
27
 
28
  export function createSettingsStore(initialValue: Omit<SettingsStore, "recentlySaved">) {
 
68
  // debounce server calls by 300ms
69
  }
70
  }
71
+ async function instantSet(settings: Partial<SettingsStore>) {
72
+ baseStore.update((s) => ({
73
+ ...s,
74
+ ...settings,
75
+ }));
76
+
77
+ if (browser) {
78
+ await fetch(`${base}/settings`, {
79
+ method: "POST",
80
+ headers: {
81
+ "Content-Type": "application/json",
82
+ },
83
+ body: JSON.stringify({
84
+ ...get(baseStore),
85
+ ...settings,
86
+ }),
87
+ });
88
+ invalidate(UrlDependency.ConversationList);
89
+ }
90
+ }
91
 
92
  const newStore = {
93
  subscribe: baseStore.subscribe,
94
  set: setSettings,
95
+ instantSet,
96
  update: (fn: (s: SettingsStore) => SettingsStore) => {
97
  setSettings(fn(get(baseStore)));
98
  },
99
+ } satisfies SettingsStoreWritable;
100
 
101
  setContext("settings", newStore);
102
 
src/routes/+layout.svelte CHANGED
@@ -116,7 +116,9 @@
116
  if ($settings.activeModel === $page.url.searchParams.get("model")) {
117
  goto(`${base}/?`);
118
  }
119
- $settings.activeModel = $page.url.searchParams.get("model") ?? $settings.activeModel;
 
 
120
  }
121
 
122
  $: mobileNavTitle = ["/models", "/assistants", "/privacy"].includes($page.route.id ?? "")
 
116
  if ($settings.activeModel === $page.url.searchParams.get("model")) {
117
  goto(`${base}/?`);
118
  }
119
+ settings.instantSet({
120
+ activeModel: $page.url.searchParams.get("model") ?? $settings.activeModel,
121
+ });
122
  }
123
 
124
  $: mobileNavTitle = ["/models", "/assistants", "/privacy"].includes($page.route.id ?? "")
src/routes/assistant/[assistantId]/+page.svelte CHANGED
@@ -8,6 +8,7 @@
8
  import { applyAction, enhance } from "$app/forms";
9
  import { PUBLIC_APP_NAME, PUBLIC_ORIGIN } from "$env/static/public";
10
  import { page } from "$app/stores";
 
11
 
12
  export let data: PageData;
13
 
@@ -47,6 +48,35 @@
47
  }}
48
  class="z-10 flex flex-col content-center items-center gap-x-10 gap-y-3 overflow-hidden rounded-2xl bg-white p-4 pt-6 text-center shadow-2xl outline-none max-sm:w-[85dvw] max-sm:px-6 md:w-96 md:grid-cols-3 md:grid-rows-[auto,1fr] md:p-8"
49
  >
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  {#if data.assistant.avatar}
51
  <img
52
  class="size-16 flex-none rounded-full object-cover sm:size-24"
 
8
  import { applyAction, enhance } from "$app/forms";
9
  import { PUBLIC_APP_NAME, PUBLIC_ORIGIN } from "$env/static/public";
10
  import { page } from "$app/stores";
11
+ import IconGear from "~icons/bi/gear-fill";
12
 
13
  export let data: PageData;
14
 
 
48
  }}
49
  class="z-10 flex flex-col content-center items-center gap-x-10 gap-y-3 overflow-hidden rounded-2xl bg-white p-4 pt-6 text-center shadow-2xl outline-none max-sm:w-[85dvw] max-sm:px-6 md:w-96 md:grid-cols-3 md:grid-rows-[auto,1fr] md:p-8"
50
  >
51
+ <div class="absolute right-0 top-0 m-6">
52
+ <form
53
+ method="POST"
54
+ action="{base}/settings/assistants/{data.assistant._id}?/subscribe"
55
+ class="w-full"
56
+ use:enhance={() => {
57
+ return async ({ result }) => {
58
+ // `result` is an `ActionResult` object
59
+ if (result.type === "success") {
60
+ $settings.activeModel = data.assistant._id;
61
+ await goto(`${base}/settings/assistants/${data.assistant._id}`, {
62
+ invalidateAll: true,
63
+ });
64
+ } else {
65
+ await applyAction(result);
66
+ }
67
+ };
68
+ }}
69
+ >
70
+ <button
71
+ class="flex items-center rounded-full border border-gray-200 px-2.5 py-1 text-sm text-gray-900 hover:bg-gray-100"
72
+ name="Settings"
73
+ type="submit"
74
+ >
75
+ <IconGear class="mr-1.5 text-xxs" />
76
+ Settings
77
+ </button>
78
+ </form>
79
+ </div>
80
  {#if data.assistant.avatar}
81
  <img
82
  class="size-16 flex-none rounded-full object-cover sm:size-24"
src/routes/assistants/+page.svelte CHANGED
@@ -17,6 +17,7 @@
17
  import Pagination from "$lib/components/Pagination.svelte";
18
  import { formatUserCount } from "$lib/utils/formatUserCount";
19
  import { getHref } from "$lib/utils/getHref";
 
20
 
21
  export let data: PageData;
22
 
@@ -30,6 +31,8 @@
30
  });
31
  goto(newUrl);
32
  };
 
 
33
  </script>
34
 
35
  <svelte:head>
@@ -143,9 +146,16 @@
143
 
144
  <div class="mt-8 grid grid-cols-2 gap-3 sm:gap-5 md:grid-cols-3 lg:grid-cols-4">
145
  {#each data.assistants as assistant (assistant._id)}
146
- <a
147
- href="{base}/assistant/{assistant._id}"
148
  class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
 
 
 
 
 
 
 
 
149
  >
150
  {#if assistant.userCount && assistant.userCount > 1}
151
  <div
@@ -186,7 +196,7 @@
186
  </a>
187
  </p>
188
  {/if}
189
- </a>
190
  {:else}
191
  No assistants found
192
  {/each}
 
17
  import Pagination from "$lib/components/Pagination.svelte";
18
  import { formatUserCount } from "$lib/utils/formatUserCount";
19
  import { getHref } from "$lib/utils/getHref";
20
+ import { useSettingsStore } from "$lib/stores/settings";
21
 
22
  export let data: PageData;
23
 
 
31
  });
32
  goto(newUrl);
33
  };
34
+
35
+ const settings = useSettingsStore();
36
  </script>
37
 
38
  <svelte:head>
 
146
 
147
  <div class="mt-8 grid grid-cols-2 gap-3 sm:gap-5 md:grid-cols-3 lg:grid-cols-4">
148
  {#each data.assistants as assistant (assistant._id)}
149
+ <button
 
150
  class="relative flex flex-col items-center justify-center overflow-hidden text-balance rounded-xl border bg-gray-50/50 px-4 py-6 text-center shadow hover:bg-gray-50 hover:shadow-inner max-sm:px-4 sm:h-64 sm:pb-4 xl:pt-8 dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
151
+ on:click={() => {
152
+ if (data.settings.assistants.includes(assistant._id.toString())) {
153
+ settings.instantSet({ activeModel: assistant._id.toString() });
154
+ goto(`${base}` || "/");
155
+ } else {
156
+ goto(`${base}/assistant/${assistant._id}`);
157
+ }
158
+ }}
159
  >
160
  {#if assistant.userCount && assistant.userCount > 1}
161
  <div
 
196
  </a>
197
  </p>
198
  {/if}
199
+ </button>
200
  {:else}
201
  No assistants found
202
  {/each}