Spaces:
Running
Running
chores(svelte): migrate `$app/stores` to `$app/state` (#1693)
Browse files- src/lib/components/AssistantSettings.svelte +3 -3
- src/lib/components/DisclaimerModal.svelte +7 -7
- src/lib/components/LoginModal.svelte +3 -3
- src/lib/components/MobileNav.svelte +3 -2
- src/lib/components/NavConversationItem.svelte +2 -2
- src/lib/components/ToolsMenu.svelte +7 -7
- src/lib/components/chat/AssistantIntroduction.svelte +2 -2
- src/lib/components/chat/ChatInput.svelte +3 -3
- src/lib/components/chat/ChatMessage.svelte +4 -4
- src/lib/components/chat/ChatWindow.svelte +5 -5
- src/lib/components/chat/ModelSwitch.svelte +3 -3
- src/lib/components/chat/ToolUpdate.svelte +2 -2
- src/lib/components/icons/Logo.svelte +2 -2
- src/routes/+error.svelte +5 -5
- src/routes/+page.svelte +2 -2
- src/routes/assistant/[assistantId]/+page.svelte +5 -5
- src/routes/assistants/+page.svelte +12 -12
- src/routes/conversation/[id]/+page.svelte +13 -13
- src/routes/models/+page.svelte +2 -2
- src/routes/models/[...model]/+page.svelte +5 -5
- src/routes/settings/(nav)/+layout.svelte +7 -7
- src/routes/settings/(nav)/assistants/[assistantId]/+page.svelte +4 -4
- src/routes/settings/(nav)/assistants/[assistantId]/edit/[email protected] +2 -2
- src/routes/tools/+layout.svelte +3 -3
- src/routes/tools/+page.svelte +13 -13
- src/routes/tools/[toolId]/+page.svelte +2 -2
src/lib/components/AssistantSettings.svelte
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
|
6 |
import { onMount } from "svelte";
|
7 |
import { applyAction, enhance } from "$app/forms";
|
8 |
-
import { page } from "$app/
|
9 |
import { base } from "$app/paths";
|
10 |
import CarbonPen from "~icons/carbon/pen";
|
11 |
import CarbonUpload from "~icons/carbon/upload";
|
@@ -140,7 +140,7 @@
|
|
140 |
|
141 |
formData.delete("ragMode");
|
142 |
|
143 |
-
if (ragMode === false ||
|
144 |
formData.set("ragAllowAll", "false");
|
145 |
formData.set("ragLinkList", "");
|
146 |
formData.set("ragDomainList", "");
|
@@ -432,7 +432,7 @@
|
|
432 |
</div>
|
433 |
<AssistantToolPicker bind:toolIds={tools} />
|
434 |
{/if}
|
435 |
-
{#if
|
436 |
<div class="flex flex-col flex-nowrap pb-4">
|
437 |
<span class="mt-2 text-smd font-semibold"
|
438 |
>Internet access
|
|
|
5 |
|
6 |
import { onMount } from "svelte";
|
7 |
import { applyAction, enhance } from "$app/forms";
|
8 |
+
import { page } from "$app/state";
|
9 |
import { base } from "$app/paths";
|
10 |
import CarbonPen from "~icons/carbon/pen";
|
11 |
import CarbonUpload from "~icons/carbon/upload";
|
|
|
140 |
|
141 |
formData.delete("ragMode");
|
142 |
|
143 |
+
if (ragMode === false || !page.data.enableAssistantsRAG) {
|
144 |
formData.set("ragAllowAll", "false");
|
145 |
formData.set("ragLinkList", "");
|
146 |
formData.set("ragDomainList", "");
|
|
|
432 |
</div>
|
433 |
<AssistantToolPicker bind:toolIds={tools} />
|
434 |
{/if}
|
435 |
+
{#if page.data.enableAssistantsRAG}
|
436 |
<div class="flex flex-col flex-nowrap pb-4">
|
437 |
<span class="mt-2 text-smd font-semibold"
|
438 |
>Internet access
|
src/lib/components/DisclaimerModal.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
-
import { page } from "$app/
|
4 |
import { env as envPublic } from "$env/dynamic/public";
|
5 |
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
@@ -31,9 +31,9 @@
|
|
31 |
<div class="flex w-full flex-col items-center gap-2">
|
32 |
<button
|
33 |
class="w-full justify-center rounded-full border-2 border-gray-300 bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
34 |
-
class:bg-white={
|
35 |
-
class:text-gray-800={
|
36 |
-
class:hover:bg-slate-100={
|
37 |
onclick={(e) => {
|
38 |
e.preventDefault();
|
39 |
e.stopPropagation();
|
@@ -44,8 +44,8 @@
|
|
44 |
$settings.ethicsModalAccepted = true;
|
45 |
}}
|
46 |
>
|
47 |
-
{#if
|
48 |
-
{#if
|
49 |
Continue as guest
|
50 |
{:else}
|
51 |
Explore the app
|
@@ -54,7 +54,7 @@
|
|
54 |
Start chatting
|
55 |
{/if}
|
56 |
</button>
|
57 |
-
{#if
|
58 |
<form action="{base}/login" target="_parent" method="POST" class="w-full">
|
59 |
<button
|
60 |
type="submit"
|
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
+
import { page } from "$app/state";
|
4 |
import { env as envPublic } from "$env/dynamic/public";
|
5 |
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
|
|
31 |
<div class="flex w-full flex-col items-center gap-2">
|
32 |
<button
|
33 |
class="w-full justify-center rounded-full border-2 border-gray-300 bg-black px-5 py-2 text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
34 |
+
class:bg-white={page.data.loginEnabled}
|
35 |
+
class:text-gray-800={page.data.loginEnabled}
|
36 |
+
class:hover:bg-slate-100={page.data.loginEnabled}
|
37 |
onclick={(e) => {
|
38 |
e.preventDefault();
|
39 |
e.stopPropagation();
|
|
|
44 |
$settings.ethicsModalAccepted = true;
|
45 |
}}
|
46 |
>
|
47 |
+
{#if page.data.loginEnabled}
|
48 |
+
{#if page.data.guestMode}
|
49 |
Continue as guest
|
50 |
{:else}
|
51 |
Explore the app
|
|
|
54 |
Start chatting
|
55 |
{/if}
|
56 |
</button>
|
57 |
+
{#if page.data.loginEnabled}
|
58 |
<form action="{base}/login" target="_parent" method="POST" class="w-full">
|
59 |
<button
|
60 |
type="submit"
|
src/lib/components/LoginModal.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
-
import { page } from "$app/
|
4 |
import { env as envPublic } from "$env/dynamic/public";
|
5 |
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
@@ -27,12 +27,12 @@
|
|
27 |
</p>
|
28 |
|
29 |
<form
|
30 |
-
action="{base}/{
|
31 |
target="_parent"
|
32 |
method="POST"
|
33 |
class="flex w-full flex-col items-center gap-2"
|
34 |
>
|
35 |
-
{#if
|
36 |
<button
|
37 |
type="submit"
|
38 |
class="flex w-full flex-wrap items-center justify-center whitespace-nowrap rounded-full bg-black px-5 py-2 text-center text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
+
import { page } from "$app/state";
|
4 |
import { env as envPublic } from "$env/dynamic/public";
|
5 |
import LogoHuggingFaceBorderless from "$lib/components/icons/LogoHuggingFaceBorderless.svelte";
|
6 |
import Modal from "$lib/components/Modal.svelte";
|
|
|
27 |
</p>
|
28 |
|
29 |
<form
|
30 |
+
action="{base}/{page.data.loginRequired ? 'login' : 'settings'}"
|
31 |
target="_parent"
|
32 |
method="POST"
|
33 |
class="flex w-full flex-col items-center gap-2"
|
34 |
>
|
35 |
+
{#if page.data.loginRequired}
|
36 |
<button
|
37 |
type="submit"
|
38 |
class="flex w-full flex-wrap items-center justify-center whitespace-nowrap rounded-full bg-black px-5 py-2 text-center text-lg font-semibold text-gray-100 transition-colors hover:bg-gray-900"
|
src/lib/components/MobileNav.svelte
CHANGED
@@ -1,7 +1,8 @@
|
|
|
|
1 |
<script lang="ts">
|
2 |
import { run } from "svelte/legacy";
|
3 |
|
4 |
-
import { navigating } from "$app/
|
5 |
import { createEventDispatcher } from "svelte";
|
6 |
import { browser } from "$app/environment";
|
7 |
import { base } from "$app/paths";
|
@@ -29,7 +30,7 @@
|
|
29 |
const dispatch = createEventDispatcher();
|
30 |
|
31 |
run(() => {
|
32 |
-
if (
|
33 |
dispatch("toggle", false);
|
34 |
}
|
35 |
});
|
|
|
1 |
+
<!-- @migration task: review uses of `navigating` -->
|
2 |
<script lang="ts">
|
3 |
import { run } from "svelte/legacy";
|
4 |
|
5 |
+
import { navigating } from "$app/state";
|
6 |
import { createEventDispatcher } from "svelte";
|
7 |
import { browser } from "$app/environment";
|
8 |
import { base } from "$app/paths";
|
|
|
30 |
const dispatch = createEventDispatcher();
|
31 |
|
32 |
run(() => {
|
33 |
+
if (navigating) {
|
34 |
dispatch("toggle", false);
|
35 |
}
|
36 |
});
|
src/lib/components/NavConversationItem.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
-
import { page } from "$app/
|
4 |
import { createEventDispatcher } from "svelte";
|
5 |
|
6 |
import CarbonCheckmark from "~icons/carbon/checkmark";
|
@@ -30,7 +30,7 @@
|
|
30 |
}}
|
31 |
href="{base}/conversation/{conv.id}"
|
32 |
class="group flex h-10 flex-none items-center gap-1.5 rounded-lg pl-2.5 pr-2 text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 sm:h-[2.35rem] {conv.id ===
|
33 |
-
|
34 |
? 'bg-gray-100 dark:bg-gray-700'
|
35 |
: ''}"
|
36 |
>
|
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
+
import { page } from "$app/state";
|
4 |
import { createEventDispatcher } from "svelte";
|
5 |
|
6 |
import CarbonCheckmark from "~icons/carbon/checkmark";
|
|
|
30 |
}}
|
31 |
href="{base}/conversation/{conv.id}"
|
32 |
class="group flex h-10 flex-none items-center gap-1.5 rounded-lg pl-2.5 pr-2 text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700 sm:h-[2.35rem] {conv.id ===
|
33 |
+
page.params.id
|
34 |
? 'bg-gray-100 dark:bg-gray-700'
|
35 |
: ''}"
|
36 |
>
|
src/lib/components/ToolsMenu.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
-
import { page } from "$app/
|
4 |
import { clickOutside } from "$lib/actions/clickOutside";
|
5 |
import { useSettingsStore } from "$lib/stores/settings";
|
6 |
import type { ToolFront } from "$lib/types/Tool";
|
@@ -20,7 +20,7 @@
|
|
20 |
|
21 |
// active tools are all the checked tools, either from settings or on by default
|
22 |
let activeToolCount = $derived(
|
23 |
-
|
24 |
(tool: ToolFront) =>
|
25 |
// community tools are always on by default
|
26 |
tool.type === "community" || $settings?.tools?.includes(tool._id)
|
@@ -28,7 +28,7 @@
|
|
28 |
);
|
29 |
|
30 |
async function setAllTools(value: boolean) {
|
31 |
-
const configToolsIds =
|
32 |
.filter((t: ToolFront) => t.type === "config")
|
33 |
.map((t: ToolFront) => t._id);
|
34 |
|
@@ -43,9 +43,9 @@
|
|
43 |
}
|
44 |
}
|
45 |
|
46 |
-
let allToolsEnabled = $derived(activeToolCount ===
|
47 |
|
48 |
-
let tools = $derived(
|
49 |
</script>
|
50 |
|
51 |
<details
|
@@ -93,7 +93,7 @@
|
|
93 |
{/if}
|
94 |
</button>
|
95 |
</div>
|
96 |
-
{#if
|
97 |
<a
|
98 |
href="{base}/tools"
|
99 |
class="col-span-2 my-1 h-fit w-fit items-center justify-center rounded-full bg-purple-500/20 px-2.5 py-1.5 text-sm hover:bg-purple-500/30"
|
@@ -101,7 +101,7 @@
|
|
101 |
<span class="mr-1 rounded-full bg-purple-700 px-1.5 py-1 text-xs font-bold uppercase">
|
102 |
new
|
103 |
</span>
|
104 |
-
Browse community tools ({
|
105 |
</a>
|
106 |
{/if}
|
107 |
{#each tools as tool}
|
|
|
1 |
<script lang="ts">
|
2 |
import { base } from "$app/paths";
|
3 |
+
import { page } from "$app/state";
|
4 |
import { clickOutside } from "$lib/actions/clickOutside";
|
5 |
import { useSettingsStore } from "$lib/stores/settings";
|
6 |
import type { ToolFront } from "$lib/types/Tool";
|
|
|
20 |
|
21 |
// active tools are all the checked tools, either from settings or on by default
|
22 |
let activeToolCount = $derived(
|
23 |
+
page.data.tools.filter(
|
24 |
(tool: ToolFront) =>
|
25 |
// community tools are always on by default
|
26 |
tool.type === "community" || $settings?.tools?.includes(tool._id)
|
|
|
28 |
);
|
29 |
|
30 |
async function setAllTools(value: boolean) {
|
31 |
+
const configToolsIds = page.data.tools
|
32 |
.filter((t: ToolFront) => t.type === "config")
|
33 |
.map((t: ToolFront) => t._id);
|
34 |
|
|
|
43 |
}
|
44 |
}
|
45 |
|
46 |
+
let allToolsEnabled = $derived(activeToolCount === page.data.tools.length);
|
47 |
|
48 |
+
let tools = $derived(page.data.tools);
|
49 |
</script>
|
50 |
|
51 |
<details
|
|
|
93 |
{/if}
|
94 |
</button>
|
95 |
</div>
|
96 |
+
{#if page.data.enableCommunityTools}
|
97 |
<a
|
98 |
href="{base}/tools"
|
99 |
class="col-span-2 my-1 h-fit w-fit items-center justify-center rounded-full bg-purple-500/20 px-2.5 py-1.5 text-sm hover:bg-purple-500/30"
|
|
|
101 |
<span class="mr-1 rounded-full bg-purple-700 px-1.5 py-1 text-xs font-bold uppercase">
|
102 |
new
|
103 |
</span>
|
104 |
+
Browse community tools ({page.data.communityToolCount ?? 0})
|
105 |
</a>
|
106 |
{/if}
|
107 |
{#each tools as tool}
|
src/lib/components/chat/AssistantIntroduction.svelte
CHANGED
@@ -16,7 +16,7 @@
|
|
16 |
|
17 |
import { share } from "$lib/utils/share";
|
18 |
import { env as envPublic } from "$env/dynamic/public";
|
19 |
-
import { page } from "$app/
|
20 |
|
21 |
interface Props {
|
22 |
models: Model[];
|
@@ -48,7 +48,7 @@
|
|
48 |
);
|
49 |
|
50 |
const prefix =
|
51 |
-
envPublic.PUBLIC_SHARE_PREFIX || `${envPublic.PUBLIC_ORIGIN ||
|
52 |
|
53 |
let shareUrl = $derived(`${prefix}/assistant/${assistant?._id}`);
|
54 |
|
|
|
16 |
|
17 |
import { share } from "$lib/utils/share";
|
18 |
import { env as envPublic } from "$env/dynamic/public";
|
19 |
+
import { page } from "$app/state";
|
20 |
|
21 |
interface Props {
|
22 |
models: Model[];
|
|
|
48 |
);
|
49 |
|
50 |
const prefix =
|
51 |
+
envPublic.PUBLIC_SHARE_PREFIX || `${envPublic.PUBLIC_ORIGIN || page.url.origin}${base}`;
|
52 |
|
53 |
let shareUrl = $derived(`${prefix}/assistant/${assistant?._id}`);
|
54 |
|
src/lib/components/chat/ChatInput.svelte
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
webSearchToolId,
|
16 |
} from "$lib/utils/toolIds";
|
17 |
import type { Assistant } from "$lib/types/Assistant";
|
18 |
-
import { page } from "$app/
|
19 |
import type { ToolFront } from "$lib/types/Tool";
|
20 |
import ToolLogo from "../ToolLogo.svelte";
|
21 |
import { goto } from "$app/navigation";
|
@@ -143,7 +143,7 @@
|
|
143 |
);
|
144 |
|
145 |
let extraTools = $derived(
|
146 |
-
|
147 |
.filter((t: ToolFront) => $settings.tools?.includes(t._id))
|
148 |
.filter(
|
149 |
(t: ToolFront) =>
|
@@ -166,7 +166,7 @@
|
|
166 |
oncompositionend={() => (isCompositionOn = false)}
|
167 |
oninput={adjustTextareaHeight}
|
168 |
onbeforeinput={(ev) => {
|
169 |
-
if (
|
170 |
ev.preventDefault();
|
171 |
$loginModalOpen = true;
|
172 |
}
|
|
|
15 |
webSearchToolId,
|
16 |
} from "$lib/utils/toolIds";
|
17 |
import type { Assistant } from "$lib/types/Assistant";
|
18 |
+
import { page } from "$app/state";
|
19 |
import type { ToolFront } from "$lib/types/Tool";
|
20 |
import ToolLogo from "../ToolLogo.svelte";
|
21 |
import { goto } from "$app/navigation";
|
|
|
143 |
);
|
144 |
|
145 |
let extraTools = $derived(
|
146 |
+
page.data.tools
|
147 |
.filter((t: ToolFront) => $settings.tools?.includes(t._id))
|
148 |
.filter(
|
149 |
(t: ToolFront) =>
|
|
|
166 |
oncompositionend={() => (isCompositionOn = false)}
|
167 |
oninput={adjustTextareaHeight}
|
168 |
onbeforeinput={(ev) => {
|
169 |
+
if (page.data.loginRequired) {
|
170 |
ev.preventDefault();
|
171 |
$loginModalOpen = true;
|
172 |
}
|
src/lib/components/chat/ChatMessage.svelte
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
|
4 |
import type { Message } from "$lib/types/Message";
|
5 |
import { createEventDispatcher, tick } from "svelte";
|
6 |
-
import { page } from "$app/
|
7 |
|
8 |
import CopyToClipBoardBtn from "../CopyToClipBoardBtn.svelte";
|
9 |
import IconLoading from "../icons/IconLoading.svelte";
|
@@ -101,7 +101,7 @@
|
|
101 |
{} as Record<string, MessageToolUpdate[]>
|
102 |
)
|
103 |
);
|
104 |
-
let urlNotTrailing = $derived(
|
105 |
let downloadLink = $derived(urlNotTrailing + `/message/${message.id}/prompt`);
|
106 |
let webSearchSources = $derived(
|
107 |
searchUpdates?.find(
|
@@ -137,9 +137,9 @@
|
|
137 |
onclick={() => (isTapped = !isTapped)}
|
138 |
onkeydown={() => (isTapped = !isTapped)}
|
139 |
>
|
140 |
-
{#if
|
141 |
<img
|
142 |
-
src="{base}/settings/assistants/{
|
143 |
alt="Avatar"
|
144 |
class="mt-5 h-3 w-3 flex-none select-none rounded-full shadow-lg"
|
145 |
/>
|
|
|
3 |
|
4 |
import type { Message } from "$lib/types/Message";
|
5 |
import { createEventDispatcher, tick } from "svelte";
|
6 |
+
import { page } from "$app/state";
|
7 |
|
8 |
import CopyToClipBoardBtn from "../CopyToClipBoardBtn.svelte";
|
9 |
import IconLoading from "../icons/IconLoading.svelte";
|
|
|
101 |
{} as Record<string, MessageToolUpdate[]>
|
102 |
)
|
103 |
);
|
104 |
+
let urlNotTrailing = $derived(page.url.pathname.replace(/\/$/, ""));
|
105 |
let downloadLink = $derived(urlNotTrailing + `/message/${message.id}/prompt`);
|
106 |
let webSearchSources = $derived(
|
107 |
searchUpdates?.find(
|
|
|
137 |
onclick={() => (isTapped = !isTapped)}
|
138 |
onkeydown={() => (isTapped = !isTapped)}
|
139 |
>
|
140 |
+
{#if page.data?.assistant?.avatar}
|
141 |
<img
|
142 |
+
src="{base}/settings/assistants/{page.data.assistant._id}/avatar.jpg"
|
143 |
alt="Avatar"
|
144 |
class="mt-5 h-3 w-3 flex-none select-none rounded-full shadow-lg"
|
145 |
/>
|
src/lib/components/chat/ChatWindow.svelte
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
import ChatInput from "./ChatInput.svelte";
|
15 |
import StopGeneratingBtn from "../StopGeneratingBtn.svelte";
|
16 |
import type { Model } from "$lib/types/Model";
|
17 |
-
import { page } from "$app/
|
18 |
import FileDropzone from "./FileDropzone.svelte";
|
19 |
import RetryBtn from "../RetryBtn.svelte";
|
20 |
import file2base64 from "$lib/utils/file2base64";
|
@@ -73,7 +73,7 @@
|
|
73 |
let pastedLongContent = $state(false);
|
74 |
|
75 |
run(() => {
|
76 |
-
|
77 |
});
|
78 |
|
79 |
const dispatch = createEventDispatcher<{
|
@@ -200,7 +200,7 @@
|
|
200 |
const settings = useSettingsStore();
|
201 |
|
202 |
let mimeTypesFromActiveTools = $derived(
|
203 |
-
|
204 |
.filter((tool: ToolFront) => {
|
205 |
if (assistant) {
|
206 |
return assistant.tools?.includes(tool._id);
|
@@ -311,7 +311,7 @@
|
|
311 |
<ChatIntroduction
|
312 |
{currentModel}
|
313 |
on:message={(ev) => {
|
314 |
-
if (
|
315 |
ev.preventDefault();
|
316 |
$loginModalOpen = true;
|
317 |
} else {
|
@@ -324,7 +324,7 @@
|
|
324 |
{models}
|
325 |
{assistant}
|
326 |
on:message={(ev) => {
|
327 |
-
if (
|
328 |
ev.preventDefault();
|
329 |
$loginModalOpen = true;
|
330 |
} else {
|
|
|
14 |
import ChatInput from "./ChatInput.svelte";
|
15 |
import StopGeneratingBtn from "../StopGeneratingBtn.svelte";
|
16 |
import type { Model } from "$lib/types/Model";
|
17 |
+
import { page } from "$app/state";
|
18 |
import FileDropzone from "./FileDropzone.svelte";
|
19 |
import RetryBtn from "../RetryBtn.svelte";
|
20 |
import file2base64 from "$lib/utils/file2base64";
|
|
|
73 |
let pastedLongContent = $state(false);
|
74 |
|
75 |
run(() => {
|
76 |
+
page.params.id && (isSharedRecently = false);
|
77 |
});
|
78 |
|
79 |
const dispatch = createEventDispatcher<{
|
|
|
200 |
const settings = useSettingsStore();
|
201 |
|
202 |
let mimeTypesFromActiveTools = $derived(
|
203 |
+
page.data.tools
|
204 |
.filter((tool: ToolFront) => {
|
205 |
if (assistant) {
|
206 |
return assistant.tools?.includes(tool._id);
|
|
|
311 |
<ChatIntroduction
|
312 |
{currentModel}
|
313 |
on:message={(ev) => {
|
314 |
+
if (page.data.loginRequired) {
|
315 |
ev.preventDefault();
|
316 |
$loginModalOpen = true;
|
317 |
} else {
|
|
|
324 |
{models}
|
325 |
{assistant}
|
326 |
on:message={(ev) => {
|
327 |
+
if (page.data.loginRequired) {
|
328 |
ev.preventDefault();
|
329 |
$loginModalOpen = true;
|
330 |
} else {
|
src/lib/components/chat/ModelSwitch.svelte
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import { invalidateAll } from "$app/navigation";
|
3 |
-
import { page } from "$app/
|
4 |
import { base } from "$app/paths";
|
5 |
import type { Model } from "$lib/types/Model";
|
6 |
|
@@ -16,10 +16,10 @@
|
|
16 |
);
|
17 |
|
18 |
async function handleModelChange() {
|
19 |
-
if (
|
20 |
|
21 |
try {
|
22 |
-
const response = await fetch(`${base}/conversation/${
|
23 |
method: "PATCH",
|
24 |
headers: {
|
25 |
"Content-Type": "application/json",
|
|
|
1 |
<script lang="ts">
|
2 |
import { invalidateAll } from "$app/navigation";
|
3 |
+
import { page } from "$app/state";
|
4 |
import { base } from "$app/paths";
|
5 |
import type { Model } from "$lib/types/Model";
|
6 |
|
|
|
16 |
);
|
17 |
|
18 |
async function handleModelChange() {
|
19 |
+
if (!page.params.id) return;
|
20 |
|
21 |
try {
|
22 |
+
const response = await fetch(`${base}/conversation/${page.params.id}`, {
|
23 |
method: "PATCH",
|
24 |
headers: {
|
25 |
"Content-Type": "application/json",
|
src/lib/components/chat/ToolUpdate.svelte
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
|
9 |
import CarbonTools from "~icons/carbon/tools";
|
10 |
import { ToolResultStatus, type ToolFront } from "$lib/types/Tool";
|
11 |
-
import { page } from "$app/
|
12 |
import { onDestroy } from "svelte";
|
13 |
import { browser } from "$app/environment";
|
14 |
|
@@ -25,7 +25,7 @@
|
|
25 |
|
26 |
let eta = $derived(tool.find((el) => el.subtype === MessageToolUpdateType.ETA)?.eta);
|
27 |
|
28 |
-
const availableTools: ToolFront[] =
|
29 |
|
30 |
let loadingBarEl: HTMLDivElement | undefined = $state();
|
31 |
let animation: Animation | undefined = $state(undefined);
|
|
|
8 |
|
9 |
import CarbonTools from "~icons/carbon/tools";
|
10 |
import { ToolResultStatus, type ToolFront } from "$lib/types/Tool";
|
11 |
+
import { page } from "$app/state";
|
12 |
import { onDestroy } from "svelte";
|
13 |
import { browser } from "$app/environment";
|
14 |
|
|
|
25 |
|
26 |
let eta = $derived(tool.find((el) => el.subtype === MessageToolUpdateType.ETA)?.eta);
|
27 |
|
28 |
+
const availableTools: ToolFront[] = page.data.tools;
|
29 |
|
30 |
let loadingBarEl: HTMLDivElement | undefined = $state();
|
31 |
let animation: Animation | undefined = $state(undefined);
|
src/lib/components/icons/Logo.svelte
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { page } from "$app/
|
3 |
import { env as envPublic } from "$env/dynamic/public";
|
4 |
import { base } from "$app/paths";
|
5 |
|
@@ -27,6 +27,6 @@
|
|
27 |
<img
|
28 |
class={classNames}
|
29 |
alt="{envPublic.PUBLIC_APP_NAME} logo"
|
30 |
-
src="{envPublic.PUBLIC_ORIGIN ||
|
31 |
/>
|
32 |
{/if}
|
|
|
1 |
<script lang="ts">
|
2 |
+
import { page } from "$app/state";
|
3 |
import { env as envPublic } from "$env/dynamic/public";
|
4 |
import { base } from "$app/paths";
|
5 |
|
|
|
27 |
<img
|
28 |
class={classNames}
|
29 |
alt="{envPublic.PUBLIC_APP_NAME} logo"
|
30 |
+
src="{envPublic.PUBLIC_ORIGIN || page.url.origin}{base}/{envPublic.PUBLIC_APP_ASSETS}/logo.svg"
|
31 |
/>
|
32 |
{/if}
|
src/routes/+error.svelte
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { page } from "$app/
|
3 |
</script>
|
4 |
|
5 |
<div
|
@@ -8,12 +8,12 @@
|
|
8 |
<div
|
9 |
class="align-center -mt-24 flex flex-col justify-center rounded-xl border bg-white px-8 pb-2 pt-4 text-center dark:border-gray-700 dark:bg-gray-800"
|
10 |
>
|
11 |
-
<h1 class="mb-2 text-5xl font-semibold">{
|
12 |
<div class="-mx-8 my-2 h-px bg-gray-200 dark:bg-gray-700"></div>
|
13 |
-
<h2 class="max-w-sm text-lg">{
|
14 |
-
{#if
|
15 |
<div class="-mx-8 my-2 h-px bg-gray-200 dark:bg-gray-700"></div>
|
16 |
-
<pre class="max-w-sm whitespace-pre-wrap text-left font-mono text-xs">{
|
17 |
.errorId}</pre>
|
18 |
{/if}
|
19 |
</div>
|
|
|
1 |
<script lang="ts">
|
2 |
+
import { page } from "$app/state";
|
3 |
</script>
|
4 |
|
5 |
<div
|
|
|
8 |
<div
|
9 |
class="align-center -mt-24 flex flex-col justify-center rounded-xl border bg-white px-8 pb-2 pt-4 text-center dark:border-gray-700 dark:bg-gray-800"
|
10 |
>
|
11 |
+
<h1 class="mb-2 text-5xl font-semibold">{page.status}</h1>
|
12 |
<div class="-mx-8 my-2 h-px bg-gray-200 dark:bg-gray-700"></div>
|
13 |
+
<h2 class="max-w-sm text-lg">{page.error?.message}</h2>
|
14 |
+
{#if page.error?.errorId}
|
15 |
<div class="-mx-8 my-2 h-px bg-gray-200 dark:bg-gray-700"></div>
|
16 |
+
<pre class="max-w-sm whitespace-pre-wrap text-left font-mono text-xs">{page.error
|
17 |
.errorId}</pre>
|
18 |
{/if}
|
19 |
</div>
|
src/routes/+page.svelte
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<script lang="ts">
|
2 |
import { goto } from "$app/navigation";
|
3 |
import { base } from "$app/paths";
|
4 |
-
import { page } from "$app/
|
5 |
import { env as envPublic } from "$env/dynamic/public";
|
6 |
import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
|
7 |
import { ERROR_MESSAGES, error } from "$lib/stores/errors";
|
@@ -75,7 +75,7 @@
|
|
75 |
|
76 |
onMount(() => {
|
77 |
// check if there's a ?q query param with a message
|
78 |
-
const query =
|
79 |
if (query) createConversation(query);
|
80 |
});
|
81 |
|
|
|
1 |
<script lang="ts">
|
2 |
import { goto } from "$app/navigation";
|
3 |
import { base } from "$app/paths";
|
4 |
+
import { page } from "$app/state";
|
5 |
import { env as envPublic } from "$env/dynamic/public";
|
6 |
import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
|
7 |
import { ERROR_MESSAGES, error } from "$lib/stores/errors";
|
|
|
75 |
|
76 |
onMount(() => {
|
77 |
// check if there's a ?q query param with a message
|
78 |
+
const query = page.url.searchParams.get("q");
|
79 |
if (query) createConversation(query);
|
80 |
});
|
81 |
|
src/routes/assistant/[assistantId]/+page.svelte
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { page } from "$app/
|
3 |
import { base } from "$app/paths";
|
4 |
import { goto } from "$app/navigation";
|
5 |
import { onMount } from "svelte";
|
@@ -16,7 +16,7 @@
|
|
16 |
let files: File[] = $state([]);
|
17 |
|
18 |
const settings = useSettingsStore();
|
19 |
-
const modelId =
|
20 |
|
21 |
async function createConversation(message: string) {
|
22 |
try {
|
@@ -62,7 +62,7 @@
|
|
62 |
activeModel: modelId,
|
63 |
});
|
64 |
|
65 |
-
const query =
|
66 |
if (query) createConversation(query);
|
67 |
});
|
68 |
</script>
|
@@ -76,10 +76,10 @@
|
|
76 |
/>
|
77 |
<meta
|
78 |
property="og:image"
|
79 |
-
content="{envPublic.PUBLIC_ORIGIN ||
|
80 |
._id}/thumbnail.png"
|
81 |
/>
|
82 |
-
<meta property="og:url" content={
|
83 |
<meta name="twitter:card" content="summary_large_image" />
|
84 |
</svelte:head>
|
85 |
|
|
|
1 |
<script lang="ts">
|
2 |
+
import { page } from "$app/state";
|
3 |
import { base } from "$app/paths";
|
4 |
import { goto } from "$app/navigation";
|
5 |
import { onMount } from "svelte";
|
|
|
16 |
let files: File[] = $state([]);
|
17 |
|
18 |
const settings = useSettingsStore();
|
19 |
+
const modelId = page.params.model;
|
20 |
|
21 |
async function createConversation(message: string) {
|
22 |
try {
|
|
|
62 |
activeModel: modelId,
|
63 |
});
|
64 |
|
65 |
+
const query = page.url.searchParams.get("q");
|
66 |
if (query) createConversation(query);
|
67 |
});
|
68 |
</script>
|
|
|
76 |
/>
|
77 |
<meta
|
78 |
property="og:image"
|
79 |
+
content="{envPublic.PUBLIC_ORIGIN || page.url.origin}{base}/assistant/{data.assistant
|
80 |
._id}/thumbnail.png"
|
81 |
/>
|
82 |
+
<meta property="og:url" content={page.url.href} />
|
83 |
<meta name="twitter:card" content="summary_large_image" />
|
84 |
</svelte:head>
|
85 |
|
src/routes/assistants/+page.svelte
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
|
7 |
import { goto } from "$app/navigation";
|
8 |
import { base } from "$app/paths";
|
9 |
-
import { page } from "$app/
|
10 |
|
11 |
import CarbonAdd from "~icons/carbon/add";
|
12 |
import CarbonHelpFilled from "~icons/carbon/help-filled";
|
@@ -34,7 +34,7 @@
|
|
34 |
|
35 |
let { data = $bindable() }: Props = $props();
|
36 |
|
37 |
-
let assistantsCreator = $derived(
|
38 |
let createdByMe = $derived(data.user?.username && data.user.username === assistantsCreator);
|
39 |
|
40 |
const SEARCH_DEBOUNCE_DELAY = 400;
|
@@ -46,7 +46,7 @@
|
|
46 |
|
47 |
const toggleShowUnfeatured = () => {
|
48 |
showUnfeatured = !showUnfeatured;
|
49 |
-
const newUrl = getHref(
|
50 |
newKeys: { showUnfeatured: showUnfeatured ? "true" : undefined },
|
51 |
existingKeys: { behaviour: "delete", keys: [] },
|
52 |
});
|
@@ -54,7 +54,7 @@
|
|
54 |
};
|
55 |
|
56 |
const onModelChange = (e: Event) => {
|
57 |
-
const newUrl = getHref(
|
58 |
newKeys: { modelId: (e.target as HTMLSelectElement).value },
|
59 |
existingKeys: { behaviour: "delete_except", keys: ["user"] },
|
60 |
});
|
@@ -75,7 +75,7 @@
|
|
75 |
}
|
76 |
|
77 |
isFilterInPorgress = true;
|
78 |
-
const newUrl = getHref(
|
79 |
newKeys: { q: value },
|
80 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
81 |
});
|
@@ -92,7 +92,7 @@
|
|
92 |
}, SEARCH_DEBOUNCE_DELAY);
|
93 |
|
94 |
const sortAssistants = () => {
|
95 |
-
const newUrl = getHref(
|
96 |
newKeys: { sort: sortValue },
|
97 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
98 |
});
|
@@ -114,9 +114,9 @@
|
|
114 |
<meta
|
115 |
property="og:image"
|
116 |
content="{envPublic.PUBLIC_ORIGIN ||
|
117 |
-
|
118 |
/>
|
119 |
-
<meta property="og:url" content={
|
120 |
{/if}
|
121 |
</svelte:head>
|
122 |
|
@@ -157,7 +157,7 @@
|
|
157 |
Show unfeatured assistants
|
158 |
</label>
|
159 |
{/if}
|
160 |
-
{#if
|
161 |
<button
|
162 |
onclick={() => {
|
163 |
$loginModalOpen = true;
|
@@ -183,7 +183,7 @@
|
|
183 |
>
|
184 |
{assistantsCreator}'s Assistants
|
185 |
<a
|
186 |
-
href={getHref(
|
187 |
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
|
188 |
})}
|
189 |
onclick={resetFilter}
|
@@ -204,7 +204,7 @@
|
|
204 |
{/if}
|
205 |
{:else}
|
206 |
<a
|
207 |
-
href={getHref(
|
208 |
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
|
209 |
})}
|
210 |
onclick={resetFilter}
|
@@ -217,7 +217,7 @@
|
|
217 |
</a>
|
218 |
{#if data.user?.username}
|
219 |
<a
|
220 |
-
href={getHref(
|
221 |
newKeys: { user: data.user.username },
|
222 |
existingKeys: { behaviour: "delete", keys: ["modelId", "p", "q"] },
|
223 |
})}
|
|
|
6 |
|
7 |
import { goto } from "$app/navigation";
|
8 |
import { base } from "$app/paths";
|
9 |
+
import { page } from "$app/state";
|
10 |
|
11 |
import CarbonAdd from "~icons/carbon/add";
|
12 |
import CarbonHelpFilled from "~icons/carbon/help-filled";
|
|
|
34 |
|
35 |
let { data = $bindable() }: Props = $props();
|
36 |
|
37 |
+
let assistantsCreator = $derived(page.url.searchParams.get("user"));
|
38 |
let createdByMe = $derived(data.user?.username && data.user.username === assistantsCreator);
|
39 |
|
40 |
const SEARCH_DEBOUNCE_DELAY = 400;
|
|
|
46 |
|
47 |
const toggleShowUnfeatured = () => {
|
48 |
showUnfeatured = !showUnfeatured;
|
49 |
+
const newUrl = getHref(page.url, {
|
50 |
newKeys: { showUnfeatured: showUnfeatured ? "true" : undefined },
|
51 |
existingKeys: { behaviour: "delete", keys: [] },
|
52 |
});
|
|
|
54 |
};
|
55 |
|
56 |
const onModelChange = (e: Event) => {
|
57 |
+
const newUrl = getHref(page.url, {
|
58 |
newKeys: { modelId: (e.target as HTMLSelectElement).value },
|
59 |
existingKeys: { behaviour: "delete_except", keys: ["user"] },
|
60 |
});
|
|
|
75 |
}
|
76 |
|
77 |
isFilterInPorgress = true;
|
78 |
+
const newUrl = getHref(page.url, {
|
79 |
newKeys: { q: value },
|
80 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
81 |
});
|
|
|
92 |
}, SEARCH_DEBOUNCE_DELAY);
|
93 |
|
94 |
const sortAssistants = () => {
|
95 |
+
const newUrl = getHref(page.url, {
|
96 |
newKeys: { sort: sortValue },
|
97 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
98 |
});
|
|
|
114 |
<meta
|
115 |
property="og:image"
|
116 |
content="{envPublic.PUBLIC_ORIGIN ||
|
117 |
+
page.url.origin}{base}/{envPublic.PUBLIC_APP_ASSETS}/assistants-thumbnail.png"
|
118 |
/>
|
119 |
+
<meta property="og:url" content={page.url.href} />
|
120 |
{/if}
|
121 |
</svelte:head>
|
122 |
|
|
|
157 |
Show unfeatured assistants
|
158 |
</label>
|
159 |
{/if}
|
160 |
+
{#if page.data.loginRequired && !data.user}
|
161 |
<button
|
162 |
onclick={() => {
|
163 |
$loginModalOpen = true;
|
|
|
183 |
>
|
184 |
{assistantsCreator}'s Assistants
|
185 |
<a
|
186 |
+
href={getHref(page.url, {
|
187 |
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
|
188 |
})}
|
189 |
onclick={resetFilter}
|
|
|
204 |
{/if}
|
205 |
{:else}
|
206 |
<a
|
207 |
+
href={getHref(page.url, {
|
208 |
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
|
209 |
})}
|
210 |
onclick={resetFilter}
|
|
|
217 |
</a>
|
218 |
{#if data.user?.username}
|
219 |
<a
|
220 |
+
href={getHref(page.url, {
|
221 |
newKeys: { user: data.user.username },
|
222 |
existingKeys: { behaviour: "delete", keys: ["modelId", "p", "q"] },
|
223 |
})}
|
src/routes/conversation/[id]/+page.svelte
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
import { pendingMessage } from "$lib/stores/pendingMessage";
|
6 |
import { isAborted } from "$lib/stores/isAborted";
|
7 |
import { onMount } from "svelte";
|
8 |
-
import { page } from "$app/
|
9 |
import { goto, invalidateAll } from "$app/navigation";
|
10 |
import { base } from "$app/paths";
|
11 |
import { shareConversation } from "$lib/shareConversation";
|
@@ -42,9 +42,9 @@
|
|
42 |
|
43 |
function createMessagesPath(messages: Message[], msgId?: Message["id"]): Message[] {
|
44 |
if (initialRun) {
|
45 |
-
if (!msgId &&
|
46 |
-
msgId =
|
47 |
-
|
48 |
}
|
49 |
if (!msgId && browser && localStorage.getItem("leafId")) {
|
50 |
msgId = localStorage.getItem("leafId") as string;
|
@@ -102,7 +102,7 @@
|
|
102 |
"Content-Type": "application/json",
|
103 |
},
|
104 |
body: JSON.stringify({
|
105 |
-
fromShare:
|
106 |
model: data.model,
|
107 |
}),
|
108 |
});
|
@@ -250,10 +250,10 @@
|
|
250 |
}
|
251 |
|
252 |
// disable websearch if assistant is present
|
253 |
-
const hasAssistant =
|
254 |
const messageUpdatesAbortController = new AbortController();
|
255 |
const messageUpdatesIterator = await fetchMessageUpdates(
|
256 |
-
|
257 |
{
|
258 |
base,
|
259 |
inputs: prompt,
|
@@ -301,13 +301,13 @@
|
|
301 |
) {
|
302 |
$error = update.message ?? "An error has occurred";
|
303 |
} else if (update.type === MessageUpdateType.Title) {
|
304 |
-
const convInData = conversations.find(({ id }) => id ===
|
305 |
if (convInData) {
|
306 |
convInData.title = update.title;
|
307 |
|
308 |
$titleUpdate = {
|
309 |
title: update.title,
|
310 |
-
convId:
|
311 |
};
|
312 |
}
|
313 |
} else if (update.type === MessageUpdateType.File) {
|
@@ -347,7 +347,7 @@
|
|
347 |
}
|
348 |
|
349 |
async function voteMessage(score: Message["score"], messageId: string) {
|
350 |
-
let conversationId =
|
351 |
let oldScore: Message["score"] | undefined;
|
352 |
|
353 |
// optimistic update to avoid waiting for the server
|
@@ -463,10 +463,10 @@
|
|
463 |
});
|
464 |
|
465 |
run(() => {
|
466 |
-
|
467 |
});
|
468 |
let title = $derived(
|
469 |
-
conversations.find((conv) => conv.id ===
|
470 |
);
|
471 |
</script>
|
472 |
|
@@ -493,7 +493,7 @@
|
|
493 |
on:continue={onContinue}
|
494 |
on:showAlternateMsg={onShowAlternateMsg}
|
495 |
on:vote={(event) => voteMessage(event.detail.score, event.detail.id)}
|
496 |
-
on:share={() => shareConversation(
|
497 |
on:stop={() => (($isAborted = true), (loading = false))}
|
498 |
models={data.models}
|
499 |
currentModel={findCurrentModel([...data.models, ...data.oldModels], data.model)}
|
|
|
5 |
import { pendingMessage } from "$lib/stores/pendingMessage";
|
6 |
import { isAborted } from "$lib/stores/isAborted";
|
7 |
import { onMount } from "svelte";
|
8 |
+
import { page } from "$app/state";
|
9 |
import { goto, invalidateAll } from "$app/navigation";
|
10 |
import { base } from "$app/paths";
|
11 |
import { shareConversation } from "$lib/shareConversation";
|
|
|
42 |
|
43 |
function createMessagesPath(messages: Message[], msgId?: Message["id"]): Message[] {
|
44 |
if (initialRun) {
|
45 |
+
if (!msgId && page.url.searchParams.get("leafId")) {
|
46 |
+
msgId = page.url.searchParams.get("leafId") as string;
|
47 |
+
page.url.searchParams.delete("leafId");
|
48 |
}
|
49 |
if (!msgId && browser && localStorage.getItem("leafId")) {
|
50 |
msgId = localStorage.getItem("leafId") as string;
|
|
|
102 |
"Content-Type": "application/json",
|
103 |
},
|
104 |
body: JSON.stringify({
|
105 |
+
fromShare: page.params.id,
|
106 |
model: data.model,
|
107 |
}),
|
108 |
});
|
|
|
250 |
}
|
251 |
|
252 |
// disable websearch if assistant is present
|
253 |
+
const hasAssistant = !!page.data.assistant;
|
254 |
const messageUpdatesAbortController = new AbortController();
|
255 |
const messageUpdatesIterator = await fetchMessageUpdates(
|
256 |
+
page.params.id,
|
257 |
{
|
258 |
base,
|
259 |
inputs: prompt,
|
|
|
301 |
) {
|
302 |
$error = update.message ?? "An error has occurred";
|
303 |
} else if (update.type === MessageUpdateType.Title) {
|
304 |
+
const convInData = conversations.find(({ id }) => id === page.params.id);
|
305 |
if (convInData) {
|
306 |
convInData.title = update.title;
|
307 |
|
308 |
$titleUpdate = {
|
309 |
title: update.title,
|
310 |
+
convId: page.params.id,
|
311 |
};
|
312 |
}
|
313 |
} else if (update.type === MessageUpdateType.File) {
|
|
|
347 |
}
|
348 |
|
349 |
async function voteMessage(score: Message["score"], messageId: string) {
|
350 |
+
let conversationId = page.params.id;
|
351 |
let oldScore: Message["score"] | undefined;
|
352 |
|
353 |
// optimistic update to avoid waiting for the server
|
|
|
463 |
});
|
464 |
|
465 |
run(() => {
|
466 |
+
page.params.id, (($isAborted = true), (loading = false));
|
467 |
});
|
468 |
let title = $derived(
|
469 |
+
conversations.find((conv) => conv.id === page.params.id)?.title ?? data.title
|
470 |
);
|
471 |
</script>
|
472 |
|
|
|
493 |
on:continue={onContinue}
|
494 |
on:showAlternateMsg={onShowAlternateMsg}
|
495 |
on:vote={(event) => voteMessage(event.detail.score, event.detail.id)}
|
496 |
+
on:share={() => shareConversation(page.params.id, data.title)}
|
497 |
on:stop={() => (($isAborted = true), (loading = false))}
|
498 |
models={data.models}
|
499 |
currentModel={findCurrentModel([...data.models, ...data.oldModels], data.model)}
|
src/routes/models/+page.svelte
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
import { isHuggingChat } from "$lib/utils/isHuggingChat";
|
6 |
|
7 |
import { base } from "$app/paths";
|
8 |
-
import { page } from "$app/
|
9 |
|
10 |
import CarbonHelpFilled from "~icons/carbon/help-filled";
|
11 |
import CarbonTools from "~icons/carbon/tools";
|
@@ -26,7 +26,7 @@
|
|
26 |
<meta property="og:title" content="HuggingChat - Models" />
|
27 |
<meta property="og:type" content="link" />
|
28 |
<meta property="og:description" content="Browse HuggingChat available models" />
|
29 |
-
<meta property="og:url" content={
|
30 |
{/if}
|
31 |
</svelte:head>
|
32 |
|
|
|
5 |
import { isHuggingChat } from "$lib/utils/isHuggingChat";
|
6 |
|
7 |
import { base } from "$app/paths";
|
8 |
+
import { page } from "$app/state";
|
9 |
|
10 |
import CarbonHelpFilled from "~icons/carbon/help-filled";
|
11 |
import CarbonTools from "~icons/carbon/tools";
|
|
|
26 |
<meta property="og:title" content="HuggingChat - Models" />
|
27 |
<meta property="og:type" content="link" />
|
28 |
<meta property="og:description" content="Browse HuggingChat available models" />
|
29 |
+
<meta property="og:url" content={page.url.href} />
|
30 |
{/if}
|
31 |
</svelte:head>
|
32 |
|
src/routes/models/[...model]/+page.svelte
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<script lang="ts">
|
2 |
-
import { page } from "$app/
|
3 |
import { base } from "$app/paths";
|
4 |
import { goto } from "$app/navigation";
|
5 |
import { onMount } from "svelte";
|
@@ -16,7 +16,7 @@
|
|
16 |
let files: File[] = $state([]);
|
17 |
|
18 |
const settings = useSettingsStore();
|
19 |
-
const modelId =
|
20 |
|
21 |
async function createConversation(message: string) {
|
22 |
try {
|
@@ -58,7 +58,7 @@
|
|
58 |
}
|
59 |
|
60 |
onMount(async () => {
|
61 |
-
const query =
|
62 |
if (query) createConversation(query);
|
63 |
|
64 |
settings.instantSet({ activeModel: modelId });
|
@@ -71,9 +71,9 @@
|
|
71 |
<meta property="og:description" content={`Use ${modelId} with ${envPublic.PUBLIC_APP_NAME}`} />
|
72 |
<meta
|
73 |
property="og:image"
|
74 |
-
content="{envPublic.PUBLIC_ORIGIN ||
|
75 |
/>
|
76 |
-
<meta property="og:url" content={
|
77 |
<meta name="twitter:card" content="summary_large_image" />
|
78 |
</svelte:head>
|
79 |
|
|
|
1 |
<script lang="ts">
|
2 |
+
import { page } from "$app/state";
|
3 |
import { base } from "$app/paths";
|
4 |
import { goto } from "$app/navigation";
|
5 |
import { onMount } from "svelte";
|
|
|
16 |
let files: File[] = $state([]);
|
17 |
|
18 |
const settings = useSettingsStore();
|
19 |
+
const modelId = page.params.model;
|
20 |
|
21 |
async function createConversation(message: string) {
|
22 |
try {
|
|
|
58 |
}
|
59 |
|
60 |
onMount(async () => {
|
61 |
+
const query = page.url.searchParams.get("q");
|
62 |
if (query) createConversation(query);
|
63 |
|
64 |
settings.instantSet({ activeModel: modelId });
|
|
|
71 |
<meta property="og:description" content={`Use ${modelId} with ${envPublic.PUBLIC_APP_NAME}`} />
|
72 |
<meta
|
73 |
property="og:image"
|
74 |
+
content="{envPublic.PUBLIC_ORIGIN || page.url.origin}{base}/models/{modelId}/thumbnail.png"
|
75 |
/>
|
76 |
+
<meta property="og:url" content={page.url.href} />
|
77 |
<meta name="twitter:card" content="summary_large_image" />
|
78 |
</svelte:head>
|
79 |
|
src/routes/settings/(nav)/+layout.svelte
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
import { onMount } from "svelte";
|
3 |
import { base } from "$app/paths";
|
4 |
import { afterNavigate, goto } from "$app/navigation";
|
5 |
-
import { page } from "$app/
|
6 |
import { useSettingsStore } from "$lib/stores/settings";
|
7 |
import CarbonClose from "~icons/carbon/close";
|
8 |
import CarbonArrowUpRight from "~icons/carbon/ArrowUpRight";
|
@@ -23,7 +23,7 @@
|
|
23 |
let assistantsSection: HTMLHeadingElement | undefined = $state();
|
24 |
|
25 |
onMount(() => {
|
26 |
-
if (
|
27 |
assistantsSection.scrollIntoView();
|
28 |
}
|
29 |
});
|
@@ -61,7 +61,7 @@
|
|
61 |
<a
|
62 |
href="{base}/settings/{model.id}"
|
63 |
class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
64 |
-
{model.id ===
|
65 |
>
|
66 |
<div class="mr-auto truncate">{model.displayName}</div>
|
67 |
|
@@ -91,7 +91,7 @@
|
|
91 |
<a
|
92 |
href="{base}/settings/assistants/{assistant._id.toString()}"
|
93 |
class="group flex h-10 flex-none items-center gap-2 pl-2 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
94 |
-
{assistant._id.toString() ===
|
95 |
>
|
96 |
{#if assistant.avatar}
|
97 |
<img
|
@@ -120,7 +120,7 @@
|
|
120 |
<a
|
121 |
href="{base}/settings/assistants/new"
|
122 |
class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
123 |
-
{
|
124 |
>
|
125 |
<CarbonAdd />
|
126 |
<div class="truncate">Create new assistant</div>
|
@@ -134,7 +134,7 @@
|
|
134 |
<a
|
135 |
href="{base}/settings/assistants/{assistant._id.toString()}"
|
136 |
class="group flex h-10 flex-none items-center gap-2 pl-2 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
137 |
-
{assistant._id.toString() ===
|
138 |
>
|
139 |
{#if assistant.avatar}
|
140 |
<img
|
@@ -171,7 +171,7 @@
|
|
171 |
<a
|
172 |
href="{base}/settings"
|
173 |
class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 max-md:order-first md:rounded-xl
|
174 |
-
{
|
175 |
>
|
176 |
<UserIcon class="text-sm" />
|
177 |
Application Settings
|
|
|
2 |
import { onMount } from "svelte";
|
3 |
import { base } from "$app/paths";
|
4 |
import { afterNavigate, goto } from "$app/navigation";
|
5 |
+
import { page } from "$app/state";
|
6 |
import { useSettingsStore } from "$lib/stores/settings";
|
7 |
import CarbonClose from "~icons/carbon/close";
|
8 |
import CarbonArrowUpRight from "~icons/carbon/ArrowUpRight";
|
|
|
23 |
let assistantsSection: HTMLHeadingElement | undefined = $state();
|
24 |
|
25 |
onMount(() => {
|
26 |
+
if (page.params?.assistantId && assistantsSection) {
|
27 |
assistantsSection.scrollIntoView();
|
28 |
}
|
29 |
});
|
|
|
61 |
<a
|
62 |
href="{base}/settings/{model.id}"
|
63 |
class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
64 |
+
{model.id === page.params.model ? '!bg-gray-100 !text-gray-800' : ''}"
|
65 |
>
|
66 |
<div class="mr-auto truncate">{model.displayName}</div>
|
67 |
|
|
|
91 |
<a
|
92 |
href="{base}/settings/assistants/{assistant._id.toString()}"
|
93 |
class="group flex h-10 flex-none items-center gap-2 pl-2 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
94 |
+
{assistant._id.toString() === page.params.assistantId ? '!bg-gray-100 !text-gray-800' : ''}"
|
95 |
>
|
96 |
{#if assistant.avatar}
|
97 |
<img
|
|
|
120 |
<a
|
121 |
href="{base}/settings/assistants/new"
|
122 |
class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
123 |
+
{page.url.pathname === `${base}/settings/assistants/new` ? '!bg-gray-100 !text-gray-800' : ''}"
|
124 |
>
|
125 |
<CarbonAdd />
|
126 |
<div class="truncate">Create new assistant</div>
|
|
|
134 |
<a
|
135 |
href="{base}/settings/assistants/{assistant._id.toString()}"
|
136 |
class="group flex h-10 flex-none items-center gap-2 pl-2 pr-2 text-sm text-gray-500 hover:bg-gray-100 md:rounded-xl
|
137 |
+
{assistant._id.toString() === page.params.assistantId ? '!bg-gray-100 !text-gray-800' : ''}"
|
138 |
>
|
139 |
{#if assistant.avatar}
|
140 |
<img
|
|
|
171 |
<a
|
172 |
href="{base}/settings"
|
173 |
class="group flex h-10 flex-none items-center gap-2 pl-3 pr-2 text-sm text-gray-500 hover:bg-gray-100 max-md:order-first md:rounded-xl
|
174 |
+
{page.url.pathname === `${base}/settings` ? '!bg-gray-100 !text-gray-800' : ''}"
|
175 |
>
|
176 |
<UserIcon class="text-sm" />
|
177 |
Application Settings
|
src/routes/settings/(nav)/assistants/[assistantId]/+page.svelte
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<script lang="ts">
|
2 |
import { enhance } from "$app/forms";
|
3 |
import { base } from "$app/paths";
|
4 |
-
import { page } from "$app/
|
5 |
import { goto } from "$app/navigation";
|
6 |
import { env as envPublic } from "$env/dynamic/public";
|
7 |
import { useSettingsStore } from "$lib/stores/settings";
|
@@ -30,13 +30,13 @@
|
|
30 |
let { data }: Props = $props();
|
31 |
|
32 |
let assistant = $derived(
|
33 |
-
data.assistants.find((el) => el._id.toString() ===
|
34 |
);
|
35 |
|
36 |
const settings = useSettingsStore();
|
37 |
|
38 |
const prefix =
|
39 |
-
envPublic.PUBLIC_SHARE_PREFIX || `${envPublic.PUBLIC_ORIGIN ||
|
40 |
|
41 |
let shareUrl = $derived(`${prefix}/assistant/${assistant?._id}`);
|
42 |
|
@@ -115,7 +115,7 @@
|
|
115 |
onclick={(e) => {
|
116 |
e.stopPropagation();
|
117 |
settings.instantSet({
|
118 |
-
activeModel:
|
119 |
});
|
120 |
goto(`${base}/`);
|
121 |
}}
|
|
|
1 |
<script lang="ts">
|
2 |
import { enhance } from "$app/forms";
|
3 |
import { base } from "$app/paths";
|
4 |
+
import { page } from "$app/state";
|
5 |
import { goto } from "$app/navigation";
|
6 |
import { env as envPublic } from "$env/dynamic/public";
|
7 |
import { useSettingsStore } from "$lib/stores/settings";
|
|
|
30 |
let { data }: Props = $props();
|
31 |
|
32 |
let assistant = $derived(
|
33 |
+
data.assistants.find((el) => el._id.toString() === page.params.assistantId)
|
34 |
);
|
35 |
|
36 |
const settings = useSettingsStore();
|
37 |
|
38 |
const prefix =
|
39 |
+
envPublic.PUBLIC_SHARE_PREFIX || `${envPublic.PUBLIC_ORIGIN || page.url.origin}${base}`;
|
40 |
|
41 |
let shareUrl = $derived(`${prefix}/assistant/${assistant?._id}`);
|
42 |
|
|
|
115 |
onclick={(e) => {
|
116 |
e.stopPropagation();
|
117 |
settings.instantSet({
|
118 |
+
activeModel: page.params.assistantId,
|
119 |
});
|
120 |
goto(`${base}/`);
|
121 |
}}
|
src/routes/settings/(nav)/assistants/[assistantId]/edit/[email protected]
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<script lang="ts">
|
2 |
import type { PageData, ActionData } from "./$types";
|
3 |
-
import { page } from "$app/
|
4 |
import AssistantSettings from "$lib/components/AssistantSettings.svelte";
|
5 |
|
6 |
interface Props {
|
@@ -10,7 +10,7 @@
|
|
10 |
|
11 |
let { data, form = $bindable() }: Props = $props();
|
12 |
|
13 |
-
let assistant = data.assistants.find((el) => el._id.toString() ===
|
14 |
</script>
|
15 |
|
16 |
<AssistantSettings bind:form {assistant} models={data.models} />
|
|
|
1 |
<script lang="ts">
|
2 |
import type { PageData, ActionData } from "./$types";
|
3 |
+
import { page } from "$app/state";
|
4 |
import AssistantSettings from "$lib/components/AssistantSettings.svelte";
|
5 |
|
6 |
interface Props {
|
|
|
10 |
|
11 |
let { data, form = $bindable() }: Props = $props();
|
12 |
|
13 |
+
let assistant = data.assistants.find((el) => el._id.toString() === page.params.assistantId);
|
14 |
</script>
|
15 |
|
16 |
<AssistantSettings bind:form {assistant} models={data.models} />
|
src/routes/tools/+layout.svelte
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
import { env as envPublic } from "$env/dynamic/public";
|
3 |
import { isHuggingChat } from "$lib/utils/isHuggingChat";
|
4 |
import { base } from "$app/paths";
|
5 |
-
import { page } from "$app/
|
6 |
interface Props {
|
7 |
children?: import("svelte").Snippet;
|
8 |
}
|
@@ -19,9 +19,9 @@
|
|
19 |
<meta
|
20 |
property="og:image"
|
21 |
content="{envPublic.PUBLIC_ORIGIN ||
|
22 |
-
|
23 |
/>
|
24 |
-
<meta property="og:url" content={
|
25 |
{/if}
|
26 |
</svelte:head>
|
27 |
|
|
|
2 |
import { env as envPublic } from "$env/dynamic/public";
|
3 |
import { isHuggingChat } from "$lib/utils/isHuggingChat";
|
4 |
import { base } from "$app/paths";
|
5 |
+
import { page } from "$app/state";
|
6 |
interface Props {
|
7 |
children?: import("svelte").Snippet;
|
8 |
}
|
|
|
19 |
<meta
|
20 |
property="og:image"
|
21 |
content="{envPublic.PUBLIC_ORIGIN ||
|
22 |
+
page.url.origin}{base}/{envPublic.PUBLIC_APP_ASSETS}/tools-thumbnail.png"
|
23 |
/>
|
24 |
+
<meta property="og:url" content={page.url.href} />
|
25 |
{/if}
|
26 |
</svelte:head>
|
27 |
|
src/routes/tools/+page.svelte
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
|
9 |
import { goto } from "$app/navigation";
|
10 |
import { base } from "$app/paths";
|
11 |
-
import { page } from "$app/
|
12 |
|
13 |
import CarbonAdd from "~icons/carbon/add";
|
14 |
import CarbonHelpFilled from "~icons/carbon/help-filled";
|
@@ -55,7 +55,7 @@
|
|
55 |
}
|
56 |
|
57 |
isFilterInPorgress = true;
|
58 |
-
const newUrl = getHref(
|
59 |
newKeys: { q: value },
|
60 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
61 |
});
|
@@ -72,7 +72,7 @@
|
|
72 |
}, SEARCH_DEBOUNCE_DELAY);
|
73 |
|
74 |
const sortTools = () => {
|
75 |
-
const newUrl = getHref(
|
76 |
newKeys: { sort: sortValue },
|
77 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
78 |
});
|
@@ -81,7 +81,7 @@
|
|
81 |
|
82 |
const toggleShowUnfeatured = () => {
|
83 |
showUnfeatured = !showUnfeatured;
|
84 |
-
const newUrl = getHref(
|
85 |
newKeys: { showUnfeatured: showUnfeatured ? "true" : undefined },
|
86 |
existingKeys: { behaviour: "delete", keys: [] },
|
87 |
});
|
@@ -89,24 +89,24 @@
|
|
89 |
};
|
90 |
|
91 |
const goToActiveUrl = () => {
|
92 |
-
return getHref(
|
93 |
newKeys: { active: "true" },
|
94 |
existingKeys: { behaviour: "delete_except", keys: ["active", "sort"] },
|
95 |
});
|
96 |
};
|
97 |
|
98 |
const goToCommunity = () => {
|
99 |
-
return getHref(
|
100 |
existingKeys: { behaviour: "delete_except", keys: ["sort", "q"] },
|
101 |
});
|
102 |
};
|
103 |
-
let activeOnly = $derived(
|
104 |
let tools = $derived(
|
105 |
data.tools.filter((t) =>
|
106 |
activeOnly ? data.settings.tools.some((toolId) => toolId === t._id.toString()) : true
|
107 |
)
|
108 |
);
|
109 |
-
let toolsCreator = $derived(
|
110 |
let createdByMe = $derived(data.user?.username && data.user.username === toolsCreator);
|
111 |
let currentModelSupportTools = $derived(
|
112 |
data.models.find((m) => m.id === $settings.activeModel)?.tools ?? false
|
@@ -150,7 +150,7 @@
|
|
150 |
Show unfeatured tools
|
151 |
</label>
|
152 |
{/if}
|
153 |
-
{#if
|
154 |
<button
|
155 |
onclick={() => {
|
156 |
$loginModalOpen = true;
|
@@ -176,7 +176,7 @@
|
|
176 |
>
|
177 |
{toolsCreator}'s tools
|
178 |
<a
|
179 |
-
href={getHref(
|
180 |
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
|
181 |
})}
|
182 |
onclick={resetFilter}
|
@@ -203,7 +203,7 @@
|
|
203 |
: 'border-transparent text-gray-400 hover:text-gray-800 dark:hover:text-gray-300'}"
|
204 |
>
|
205 |
<CarbonEarthAmerica class="text-xs" />
|
206 |
-
Active ({
|
207 |
</a>
|
208 |
<a
|
209 |
href={goToCommunity()}
|
@@ -217,7 +217,7 @@
|
|
217 |
</a>
|
218 |
{#if data.user?.username}
|
219 |
<a
|
220 |
-
href={getHref(
|
221 |
newKeys: { user: data.user.username },
|
222 |
existingKeys: { behaviour: "delete", keys: ["modelId", "p", "q", "active"] },
|
223 |
})}
|
@@ -265,7 +265,7 @@
|
|
265 |
|
266 |
<div class="mt-4 grid grid-cols-1 gap-3 sm:gap-5 lg:grid-cols-2">
|
267 |
{#each tools as tool}
|
268 |
-
{@const isActive = (
|
269 |
{@const isOfficial = !tool.createdByName}
|
270 |
<div
|
271 |
onclick={() => goto(`${base}/tools/${tool._id.toString()}`)}
|
|
|
8 |
|
9 |
import { goto } from "$app/navigation";
|
10 |
import { base } from "$app/paths";
|
11 |
+
import { page } from "$app/state";
|
12 |
|
13 |
import CarbonAdd from "~icons/carbon/add";
|
14 |
import CarbonHelpFilled from "~icons/carbon/help-filled";
|
|
|
55 |
}
|
56 |
|
57 |
isFilterInPorgress = true;
|
58 |
+
const newUrl = getHref(page.url, {
|
59 |
newKeys: { q: value },
|
60 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
61 |
});
|
|
|
72 |
}, SEARCH_DEBOUNCE_DELAY);
|
73 |
|
74 |
const sortTools = () => {
|
75 |
+
const newUrl = getHref(page.url, {
|
76 |
newKeys: { sort: sortValue },
|
77 |
existingKeys: { behaviour: "delete", keys: ["p"] },
|
78 |
});
|
|
|
81 |
|
82 |
const toggleShowUnfeatured = () => {
|
83 |
showUnfeatured = !showUnfeatured;
|
84 |
+
const newUrl = getHref(page.url, {
|
85 |
newKeys: { showUnfeatured: showUnfeatured ? "true" : undefined },
|
86 |
existingKeys: { behaviour: "delete", keys: [] },
|
87 |
});
|
|
|
89 |
};
|
90 |
|
91 |
const goToActiveUrl = () => {
|
92 |
+
return getHref(page.url, {
|
93 |
newKeys: { active: "true" },
|
94 |
existingKeys: { behaviour: "delete_except", keys: ["active", "sort"] },
|
95 |
});
|
96 |
};
|
97 |
|
98 |
const goToCommunity = () => {
|
99 |
+
return getHref(page.url, {
|
100 |
existingKeys: { behaviour: "delete_except", keys: ["sort", "q"] },
|
101 |
});
|
102 |
};
|
103 |
+
let activeOnly = $derived(page.url.searchParams.get("active") === "true");
|
104 |
let tools = $derived(
|
105 |
data.tools.filter((t) =>
|
106 |
activeOnly ? data.settings.tools.some((toolId) => toolId === t._id.toString()) : true
|
107 |
)
|
108 |
);
|
109 |
+
let toolsCreator = $derived(page.url.searchParams.get("user"));
|
110 |
let createdByMe = $derived(data.user?.username && data.user.username === toolsCreator);
|
111 |
let currentModelSupportTools = $derived(
|
112 |
data.models.find((m) => m.id === $settings.activeModel)?.tools ?? false
|
|
|
150 |
Show unfeatured tools
|
151 |
</label>
|
152 |
{/if}
|
153 |
+
{#if page.data.loginRequired && !data.user}
|
154 |
<button
|
155 |
onclick={() => {
|
156 |
$loginModalOpen = true;
|
|
|
176 |
>
|
177 |
{toolsCreator}'s tools
|
178 |
<a
|
179 |
+
href={getHref(page.url, {
|
180 |
existingKeys: { behaviour: "delete", keys: ["user", "modelId", "p", "q"] },
|
181 |
})}
|
182 |
onclick={resetFilter}
|
|
|
203 |
: 'border-transparent text-gray-400 hover:text-gray-800 dark:hover:text-gray-300'}"
|
204 |
>
|
205 |
<CarbonEarthAmerica class="text-xs" />
|
206 |
+
Active ({page.data.settings?.tools?.length})
|
207 |
</a>
|
208 |
<a
|
209 |
href={goToCommunity()}
|
|
|
217 |
</a>
|
218 |
{#if data.user?.username}
|
219 |
<a
|
220 |
+
href={getHref(page.url, {
|
221 |
newKeys: { user: data.user.username },
|
222 |
existingKeys: { behaviour: "delete", keys: ["modelId", "p", "q", "active"] },
|
223 |
})}
|
|
|
265 |
|
266 |
<div class="mt-4 grid grid-cols-1 gap-3 sm:gap-5 lg:grid-cols-2">
|
267 |
{#each tools as tool}
|
268 |
+
{@const isActive = (page.data.settings?.tools ?? []).includes(tool._id.toString())}
|
269 |
{@const isOfficial = !tool.createdByName}
|
270 |
<div
|
271 |
onclick={() => goto(`${base}/tools/${tool._id.toString()}`)}
|
src/routes/tools/[toolId]/+page.svelte
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<script lang="ts">
|
2 |
import { afterNavigate, goto } from "$app/navigation";
|
3 |
import { base } from "$app/paths";
|
4 |
-
import { page } from "$app/
|
5 |
import Modal from "$lib/components/Modal.svelte";
|
6 |
import ToolLogo from "$lib/components/ToolLogo.svelte";
|
7 |
import { env as envPublic } from "$env/dynamic/public";
|
@@ -33,7 +33,7 @@
|
|
33 |
});
|
34 |
|
35 |
const prefix =
|
36 |
-
envPublic.PUBLIC_SHARE_PREFIX || `${envPublic.PUBLIC_ORIGIN ||
|
37 |
|
38 |
let shareUrl = $derived(`${prefix}/tools/${data.tool?._id}`);
|
39 |
let isActive = $derived($settings.tools?.includes(data.tool?._id.toString()));
|
|
|
1 |
<script lang="ts">
|
2 |
import { afterNavigate, goto } from "$app/navigation";
|
3 |
import { base } from "$app/paths";
|
4 |
+
import { page } from "$app/state";
|
5 |
import Modal from "$lib/components/Modal.svelte";
|
6 |
import ToolLogo from "$lib/components/ToolLogo.svelte";
|
7 |
import { env as envPublic } from "$env/dynamic/public";
|
|
|
33 |
});
|
34 |
|
35 |
const prefix =
|
36 |
+
envPublic.PUBLIC_SHARE_PREFIX || `${envPublic.PUBLIC_ORIGIN || page.url.origin}${base}`;
|
37 |
|
38 |
let shareUrl = $derived(`${prefix}/tools/${data.tool?._id}`);
|
39 |
let isActive = $derived($settings.tools?.includes(data.tool?._id.toString()));
|