diff --git a/client/.yarn/install-state.gz b/client/.yarn/install-state.gz
index e1d822b..8aac8da 100644
Binary files a/client/.yarn/install-state.gz and b/client/.yarn/install-state.gz differ
diff --git a/client/app/components.d.ts b/client/app/components.d.ts
index 88eb6f6..d90c971 100644
--- a/client/app/components.d.ts
+++ b/client/app/components.d.ts
@@ -13,17 +13,19 @@ declare module 'vue' {
PrimeButton: typeof import('primevue/button')['default']
PrimeButtonGroup: typeof import('primevue/buttongroup')['default']
PrimeCard: typeof import('primevue/card')['default']
- PrimeDivider: typeof import('primevue/divider')['default']
PrimeFloatLabel: typeof import('primevue/floatlabel')['default']
PrimeInputText: typeof import('primevue/inputtext')['default']
PrimePassword: typeof import('primevue/password')['default']
- PrimeProgressBar: typeof import('primevue/progressbar')['default']
PrimeScrollPanel: typeof import('primevue/scrollpanel')['default']
- PrimeSelect: typeof import('primevue/select')['default']
PrimeSelectButton: typeof import('primevue/selectbutton')['default']
PrimeSlider: typeof import('primevue/slider')['default']
+ PrimeTab: typeof import('primevue/tab')['default']
+ PrimeTabList: typeof import('primevue/tablist')['default']
+ PrimeTabPanel: typeof import('primevue/tabpanel')['default']
+ PrimeTabPanels: typeof import('primevue/tabpanels')['default']
+ PrimeTabs: typeof import('primevue/tabs')['default']
+ PrimeTextarea: typeof import('primevue/textarea')['default']
PrimeToast: typeof import('primevue/toast')['default']
- PrimeToggleSwitch: typeof import('primevue/toggleswitch')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
}
diff --git a/client/app/components/chat/ChatEditor.vue b/client/app/components/chat/ChatEditor.vue
new file mode 100644
index 0000000..d8d1de0
--- /dev/null
+++ b/client/app/components/chat/ChatEditor.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/client/app/components/chat/ChatMessage.vue b/client/app/components/chat/ChatMessage.vue
new file mode 100644
index 0000000..e52f7ed
--- /dev/null
+++ b/client/app/components/chat/ChatMessage.vue
@@ -0,0 +1,27 @@
+
+
+
+
+ {{ username }}
+
+
+
+ {{ message }}
+
+
+ {{ createdAt }}
+
+
+
+
+
+
+
diff --git a/client/app/components/chat/ChatWidget.vue b/client/app/components/chat/ChatWidget.vue
new file mode 100644
index 0000000..10ed74e
--- /dev/null
+++ b/client/app/components/chat/ChatWidget.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+ Channel: {{ channel }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/client/app/composables/use-chat.ts b/client/app/composables/use-chat.ts
new file mode 100644
index 0000000..3b66579
--- /dev/null
+++ b/client/app/composables/use-chat.ts
@@ -0,0 +1,44 @@
+import { createGlobalState } from '@vueuse/core'
+
+interface ChatMessage {
+ id: string
+ username: string
+ message: string
+}
+
+interface ChatChannel {
+ id: number
+ name: string
+}
+
+export const useChat = createGlobalState(() => {
+ const messages = ref([
+ {
+ id: '1337',
+ username: 'Yes',
+ message: 'Fisting is 300 bucks',
+ createdAt: Date.now(),
+ },
+ ])
+
+ const channel = ref(0)
+
+ async function sendMsg(channelId: ChatChannel['id'], msg: ChatMessage['message']) {
+ console.log('Trying to send message', channelId, msg)
+ }
+
+ watch(channel, async (id) => {
+ await console.log('Yes', id)
+ }, {
+ immediate: true,
+ })
+
+ return {
+ channel,
+
+ channels,
+ messages,
+
+ sendMsg,
+ }
+})
diff --git a/client/app/pages/index.vue b/client/app/pages/index.vue
index ab276f5..e98da71 100644
--- a/client/app/pages/index.vue
+++ b/client/app/pages/index.vue
@@ -3,7 +3,7 @@
- The chat is under development.
+
diff --git a/client/src-tauri/src/lib.rs b/client/src-tauri/src/lib.rs
index f0bf59b..0f33475 100644
--- a/client/src-tauri/src/lib.rs
+++ b/client/src-tauri/src/lib.rs
@@ -4,7 +4,7 @@ pub fn run() {
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_updater::Builder::new().build())
- .plugin(tauri_plugin_single_instance::init(|_, _, _| {}))
+// .plugin(tauri_plugin_single_instance::init(|_, _, _| {}))
.setup(|app| {
if cfg!(debug_assertions) {
app.handle().plugin(
diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity
new file mode 100644
index 0000000..c8ffeba
--- /dev/null
+++ b/node_modules/.yarn-integrity
@@ -0,0 +1,12 @@
+{
+ "systemParams": "win32-x64-137",
+ "modulesFolders": [
+ "node_modules"
+ ],
+ "flags": [],
+ "linkedModules": [],
+ "topLevelPatterns": [],
+ "lockfileEntries": {},
+ "files": [],
+ "artifacts": {}
+}
\ No newline at end of file
diff --git a/server/modules/chat/index.ts b/server/modules/chat/index.ts
new file mode 100644
index 0000000..c035914
--- /dev/null
+++ b/server/modules/chat/index.ts
@@ -0,0 +1,22 @@
+import client from '../../prisma/client.ts'
+
+export async function chatInit() {
+ const existing = client.chatChannel.findFirst({
+ where: {
+ id: 0,
+ },
+ })
+
+ if (!existing) {
+ await client.chatChannel.create({
+ create: {
+ id: 0,
+ name: 'Main channel',
+ },
+ update: null,
+ where: {
+ id: 0,
+ },
+ })
+ }
+}
diff --git a/server/prisma/migrations/20251226183651_minus_nahuy/migration.sql b/server/prisma/migrations/20251226183651_minus_nahuy/migration.sql
new file mode 100644
index 0000000..e9931e2
--- /dev/null
+++ b/server/prisma/migrations/20251226183651_minus_nahuy/migration.sql
@@ -0,0 +1,20 @@
+/*
+ Warnings:
+
+ - You are about to drop the column `volumes` on the `UserPreferences` table. All the data in the column will be lost.
+
+*/
+-- RedefineTables
+PRAGMA defer_foreign_keys=ON;
+PRAGMA foreign_keys=OFF;
+CREATE TABLE "new_UserPreferences" (
+ "userId" TEXT NOT NULL PRIMARY KEY,
+ "toggleInputHotkey" TEXT DEFAULT '',
+ "toggleOutputHotkey" TEXT DEFAULT '',
+ CONSTRAINT "UserPreferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+INSERT INTO "new_UserPreferences" ("toggleInputHotkey", "toggleOutputHotkey", "userId") SELECT "toggleInputHotkey", "toggleOutputHotkey", "userId" FROM "UserPreferences";
+DROP TABLE "UserPreferences";
+ALTER TABLE "new_UserPreferences" RENAME TO "UserPreferences";
+PRAGMA foreign_keys=ON;
+PRAGMA defer_foreign_keys=OFF;
diff --git a/server/prisma/migrations/20251226190516_chat/migration.sql b/server/prisma/migrations/20251226190516_chat/migration.sql
new file mode 100644
index 0000000..515418e
--- /dev/null
+++ b/server/prisma/migrations/20251226190516_chat/migration.sql
@@ -0,0 +1,18 @@
+-- CreateTable
+CREATE TABLE "ChatMessage" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "userId" TEXT NOT NULL,
+ "channelId" TEXT NOT NULL,
+ "content" TEXT NOT NULL DEFAULT '',
+ CONSTRAINT "ChatMessage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
+ CONSTRAINT "ChatMessage_channelId_fkey" FOREIGN KEY ("channelId") REFERENCES "ChatChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+
+-- CreateTable
+CREATE TABLE "ChatChannel" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "name" TEXT NOT NULL
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "ChatChannel_name_key" ON "ChatChannel"("name");
diff --git a/server/prisma/migrations/20251226194252_more_chat_wip/migration.sql b/server/prisma/migrations/20251226194252_more_chat_wip/migration.sql
new file mode 100644
index 0000000..eefb751
--- /dev/null
+++ b/server/prisma/migrations/20251226194252_more_chat_wip/migration.sql
@@ -0,0 +1,34 @@
+/*
+ Warnings:
+
+ - The primary key for the `ChatChannel` table will be changed. If it partially fails, the table could be left without primary key constraint.
+ - You are about to alter the column `id` on the `ChatChannel` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`.
+ - You are about to alter the column `channelId` on the `ChatMessage` table. The data in that column could be lost. The data in that column will be cast from `String` to `Int`.
+ - Added the required column `createdAt` to the `ChatMessage` table without a default value. This is not possible if the table is not empty.
+
+*/
+-- RedefineTables
+PRAGMA defer_foreign_keys=ON;
+PRAGMA foreign_keys=OFF;
+CREATE TABLE "new_ChatChannel" (
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ "name" TEXT NOT NULL
+);
+INSERT INTO "new_ChatChannel" ("id", "name") SELECT "id", "name" FROM "ChatChannel";
+DROP TABLE "ChatChannel";
+ALTER TABLE "new_ChatChannel" RENAME TO "ChatChannel";
+CREATE UNIQUE INDEX "ChatChannel_name_key" ON "ChatChannel"("name");
+CREATE TABLE "new_ChatMessage" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "userId" TEXT NOT NULL,
+ "channelId" INTEGER NOT NULL,
+ "content" TEXT NOT NULL DEFAULT '',
+ "createdAt" DATETIME NOT NULL,
+ CONSTRAINT "ChatMessage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
+ CONSTRAINT "ChatMessage_channelId_fkey" FOREIGN KEY ("channelId") REFERENCES "ChatChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+INSERT INTO "new_ChatMessage" ("channelId", "content", "id", "userId") SELECT "channelId", "content", "id", "userId" FROM "ChatMessage";
+DROP TABLE "ChatMessage";
+ALTER TABLE "new_ChatMessage" RENAME TO "ChatMessage";
+PRAGMA foreign_keys=ON;
+PRAGMA defer_foreign_keys=OFF;
diff --git a/server/prisma/migrations/20251226194927_more_chat_wip/migration.sql b/server/prisma/migrations/20251226194927_more_chat_wip/migration.sql
new file mode 100644
index 0000000..87af6c4
--- /dev/null
+++ b/server/prisma/migrations/20251226194927_more_chat_wip/migration.sql
@@ -0,0 +1,17 @@
+-- RedefineTables
+PRAGMA defer_foreign_keys=ON;
+PRAGMA foreign_keys=OFF;
+CREATE TABLE "new_ChatMessage" (
+ "id" TEXT NOT NULL PRIMARY KEY,
+ "userId" TEXT NOT NULL,
+ "channelId" INTEGER NOT NULL,
+ "content" TEXT NOT NULL,
+ "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ CONSTRAINT "ChatMessage_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
+ CONSTRAINT "ChatMessage_channelId_fkey" FOREIGN KEY ("channelId") REFERENCES "ChatChannel" ("id") ON DELETE CASCADE ON UPDATE CASCADE
+);
+INSERT INTO "new_ChatMessage" ("channelId", "content", "createdAt", "id", "userId") SELECT "channelId", "content", "createdAt", "id", "userId" FROM "ChatMessage";
+DROP TABLE "ChatMessage";
+ALTER TABLE "new_ChatMessage" RENAME TO "ChatMessage";
+PRAGMA foreign_keys=ON;
+PRAGMA defer_foreign_keys=OFF;
diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma
index 8477571..3f15326 100644
--- a/server/prisma/schema.prisma
+++ b/server/prisma/schema.prisma
@@ -18,6 +18,8 @@ model User {
Session Session[]
UserPreferences UserPreferences?
+
+ ChatMessage ChatMessage[]
}
model Session {
@@ -34,7 +36,26 @@ model UserPreferences {
userId String @id
toggleInputHotkey String? @default("")
toggleOutputHotkey String? @default("")
- volumes Json? @default("{}")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+}
+
+model ChatMessage {
+ id String @id
+
+ userId String
+ channelId Int
+ content String
+
+ createdAt DateTime @default(now())
+
+ user User @relation(fields: [userId], references: [id], onDelete: Restrict)
+ channel ChatChannel @relation(fields: [channelId], references: [id], onDelete: Cascade)
+}
+
+model ChatChannel {
+ id Int @id
+ name String @unique
+
+ messages ChatMessage[]
}
\ No newline at end of file
diff --git a/server/routes/chat.ts b/server/routes/chat.ts
new file mode 100644
index 0000000..ee2aded
--- /dev/null
+++ b/server/routes/chat.ts
@@ -0,0 +1,23 @@
+import type { FastifyInstance } from 'fastify'
+import prisma from '../prisma/client.ts'
+
+export default function (fastify: FastifyInstance) {
+ fastify.get('/chats', async (req, reply) => {
+ if (req.user) {
+ return prisma.chatChannel.findMany()
+ }
+
+ reply.code(401).send(false)
+ })
+
+ fastify.get('/chats/:id', async (req, reply) => {
+ if (req.user) {
+ console.log('Trying to fetch chat with id', req.body.id)
+
+ // return prisma.userPreferences.findFirst({ where: { userId: req.user.id } })
+ return true
+ }
+
+ reply.code(401).send(false)
+ })
+}
diff --git a/server/server.ts b/server/server.ts
index 53ab88c..2a73772 100644
--- a/server/server.ts
+++ b/server/server.ts
@@ -4,6 +4,7 @@ import FastifyAutoLoad from '@fastify/autoload'
import FastifyCookie from '@fastify/cookie'
import FastifyCors from '@fastify/cors'
import Fastify from 'fastify'
+import { chatInit } from './modules/chat/index.ts'
import prisma from './prisma/client.ts'
const __filename = fileURLToPath(import.meta.url)
@@ -43,6 +44,8 @@ fastify.register(FastifyAutoLoad, {
await prisma.$connect()
fastify.log.info('Testing DB Connection. OK')
+
+ await chatInit()
}
catch (err) {
fastify.log.error(err)
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 0000000..fb57ccd
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,4 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+