Spaces:
Paused
Paused
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<
|
| 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
|
| 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 |
-
|
|
|
|
|
|
|
| 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 |
-
<
|
| 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 |
-
</
|
| 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}
|