✨ Can chat in shared convo (#55)
Browse files- package-lock.json +10 -1
- package.json +2 -1
- src/lib/types/Conversation.ts +4 -0
- src/routes/conversation/+server.ts +31 -3
- src/routes/conversation/[id]/+page.svelte +1 -3
- src/routes/r/[id]/+page.svelte +37 -1
package-lock.json
CHANGED
|
@@ -18,7 +18,8 @@
|
|
| 18 |
"nanoid": "^4.0.2",
|
| 19 |
"postcss": "^8.4.21",
|
| 20 |
"tailwind-scrollbar": "^3.0.0",
|
| 21 |
-
"tailwindcss": "^3.3.1"
|
|
|
|
| 22 |
},
|
| 23 |
"devDependencies": {
|
| 24 |
"@iconify-json/carbon": "^1.1.16",
|
|
@@ -4138,6 +4139,14 @@
|
|
| 4138 |
"funding": {
|
| 4139 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 4140 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4141 |
}
|
| 4142 |
}
|
| 4143 |
}
|
|
|
|
| 18 |
"nanoid": "^4.0.2",
|
| 19 |
"postcss": "^8.4.21",
|
| 20 |
"tailwind-scrollbar": "^3.0.0",
|
| 21 |
+
"tailwindcss": "^3.3.1",
|
| 22 |
+
"zod": "^3.21.4"
|
| 23 |
},
|
| 24 |
"devDependencies": {
|
| 25 |
"@iconify-json/carbon": "^1.1.16",
|
|
|
|
| 4139 |
"funding": {
|
| 4140 |
"url": "https://github.com/sponsors/sindresorhus"
|
| 4141 |
}
|
| 4142 |
+
},
|
| 4143 |
+
"node_modules/zod": {
|
| 4144 |
+
"version": "3.21.4",
|
| 4145 |
+
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
| 4146 |
+
"integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
|
| 4147 |
+
"funding": {
|
| 4148 |
+
"url": "https://github.com/sponsors/colinhacks"
|
| 4149 |
+
}
|
| 4150 |
}
|
| 4151 |
}
|
| 4152 |
}
|
package.json
CHANGED
|
@@ -43,6 +43,7 @@
|
|
| 43 |
"nanoid": "^4.0.2",
|
| 44 |
"postcss": "^8.4.21",
|
| 45 |
"tailwind-scrollbar": "^3.0.0",
|
| 46 |
-
"tailwindcss": "^3.3.1"
|
|
|
|
| 47 |
}
|
| 48 |
}
|
|
|
|
| 43 |
"nanoid": "^4.0.2",
|
| 44 |
"postcss": "^8.4.21",
|
| 45 |
"tailwind-scrollbar": "^3.0.0",
|
| 46 |
+
"tailwindcss": "^3.3.1",
|
| 47 |
+
"zod": "^3.21.4"
|
| 48 |
}
|
| 49 |
}
|
src/lib/types/Conversation.ts
CHANGED
|
@@ -12,4 +12,8 @@ export interface Conversation {
|
|
| 12 |
|
| 13 |
createdAt: Date;
|
| 14 |
updatedAt: Date;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
|
|
|
| 12 |
|
| 13 |
createdAt: Date;
|
| 14 |
updatedAt: Date;
|
| 15 |
+
|
| 16 |
+
meta?: {
|
| 17 |
+
fromShareId?: string;
|
| 18 |
+
};
|
| 19 |
}
|
src/routes/conversation/+server.ts
CHANGED
|
@@ -1,19 +1,47 @@
|
|
| 1 |
import type { RequestHandler } from "./$types";
|
| 2 |
import { collections } from "$lib/server/database";
|
| 3 |
import { ObjectId } from "mongodb";
|
| 4 |
-
import { redirect } from "@sveltejs/kit";
|
| 5 |
import { base } from "$app/paths";
|
|
|
|
|
|
|
| 6 |
|
| 7 |
export const POST: RequestHandler = async (input) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
const res = await collections.conversations.insertOne({
|
| 9 |
_id: new ObjectId(),
|
| 10 |
title:
|
|
|
|
| 11 |
"Untitled " +
|
| 12 |
-
|
| 13 |
-
|
|
|
|
| 14 |
createdAt: new Date(),
|
| 15 |
updatedAt: new Date(),
|
| 16 |
sessionId: input.locals.sessionId,
|
|
|
|
| 17 |
});
|
| 18 |
|
| 19 |
return new Response(
|
|
|
|
| 1 |
import type { RequestHandler } from "./$types";
|
| 2 |
import { collections } from "$lib/server/database";
|
| 3 |
import { ObjectId } from "mongodb";
|
| 4 |
+
import { error, redirect } from "@sveltejs/kit";
|
| 5 |
import { base } from "$app/paths";
|
| 6 |
+
import { z } from "zod";
|
| 7 |
+
import type { Message } from "$lib/types/Message";
|
| 8 |
|
| 9 |
export const POST: RequestHandler = async (input) => {
|
| 10 |
+
const body = await input.request.text();
|
| 11 |
+
|
| 12 |
+
let title = "";
|
| 13 |
+
let messages: Message[] = [];
|
| 14 |
+
let fromShareId: string | undefined;
|
| 15 |
+
|
| 16 |
+
if (body) {
|
| 17 |
+
fromShareId = z.object({ fromShare: z.string().optional() }).parse(JSON.parse(body)).fromShare;
|
| 18 |
+
|
| 19 |
+
if (fromShareId) {
|
| 20 |
+
const conversation = await collections.sharedConversations.findOne({
|
| 21 |
+
_id: fromShareId,
|
| 22 |
+
});
|
| 23 |
+
|
| 24 |
+
if (!conversation) {
|
| 25 |
+
throw error(404, "Conversation not found");
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
title = conversation.title;
|
| 29 |
+
messages = conversation.messages;
|
| 30 |
+
}
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
const res = await collections.conversations.insertOne({
|
| 34 |
_id: new ObjectId(),
|
| 35 |
title:
|
| 36 |
+
title ||
|
| 37 |
"Untitled " +
|
| 38 |
+
((await collections.conversations.countDocuments({ sessionId: input.locals.sessionId })) +
|
| 39 |
+
1),
|
| 40 |
+
messages,
|
| 41 |
createdAt: new Date(),
|
| 42 |
updatedAt: new Date(),
|
| 43 |
sessionId: input.locals.sessionId,
|
| 44 |
+
...(fromShareId ? { meta: { fromShareId } } : {}),
|
| 45 |
});
|
| 46 |
|
| 47 |
return new Response(
|
src/routes/conversation/[id]/+page.svelte
CHANGED
|
@@ -81,9 +81,7 @@
|
|
| 81 |
const val = $pendingMessage;
|
| 82 |
$pendingMessage = "";
|
| 83 |
|
| 84 |
-
|
| 85 |
-
writeMessage(val);
|
| 86 |
-
}
|
| 87 |
}
|
| 88 |
});
|
| 89 |
</script>
|
|
|
|
| 81 |
const val = $pendingMessage;
|
| 82 |
$pendingMessage = "";
|
| 83 |
|
| 84 |
+
writeMessage(val);
|
|
|
|
|
|
|
| 85 |
}
|
| 86 |
});
|
| 87 |
</script>
|
src/routes/r/[id]/+page.svelte
CHANGED
|
@@ -1,8 +1,44 @@
|
|
| 1 |
<script lang="ts">
|
|
|
|
|
|
|
|
|
|
| 2 |
import ChatWindow from "$lib/components/chat/ChatWindow.svelte";
|
|
|
|
| 3 |
import type { PageData } from "./$types";
|
| 4 |
|
| 5 |
export let data: PageData;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
</script>
|
| 7 |
|
| 8 |
-
<ChatWindow
|
|
|
|
| 1 |
<script lang="ts">
|
| 2 |
+
import { goto } from "$app/navigation";
|
| 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 |
|
| 9 |
export let data: PageData;
|
| 10 |
+
|
| 11 |
+
let loading = false;
|
| 12 |
+
|
| 13 |
+
async function createConversation(message: string) {
|
| 14 |
+
try {
|
| 15 |
+
loading = true;
|
| 16 |
+
const res = await fetch(`${base}/conversation`, {
|
| 17 |
+
method: "POST",
|
| 18 |
+
headers: {
|
| 19 |
+
"Content-Type": "application/json",
|
| 20 |
+
},
|
| 21 |
+
body: JSON.stringify({
|
| 22 |
+
fromShare: $page.params.id,
|
| 23 |
+
}),
|
| 24 |
+
});
|
| 25 |
+
|
| 26 |
+
if (!res.ok) {
|
| 27 |
+
alert("Error while creating conversation: " + (await res.text()));
|
| 28 |
+
return;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
const { conversationId } = await res.json();
|
| 32 |
+
|
| 33 |
+
// Ugly hack to use a store as temp storage, feel free to improve ^^
|
| 34 |
+
pendingMessage.set(message);
|
| 35 |
+
|
| 36 |
+
// invalidateAll to update list of conversations
|
| 37 |
+
await goto(`${base}/conversation/${conversationId}`, { invalidateAll: true });
|
| 38 |
+
} finally {
|
| 39 |
+
loading = false;
|
| 40 |
+
}
|
| 41 |
+
}
|
| 42 |
</script>
|
| 43 |
|
| 44 |
+
<ChatWindow on:message={(ev) => createConversation(ev.detail)} messages={data.messages} {loading} />
|