From 95dd2445c268bb7e1d3b10e4b3064d3a6b14c33c Mon Sep 17 00:00:00 2001
From: Brieuc Dubois <git@bhasher.com>
Date: Tue, 23 Jul 2024 10:58:40 +0200
Subject: [PATCH] Rename spellcheck -> feedback & real time sync

---
 backend/app/crud.py                           | 14 +++++-----
 backend/app/main.py                           | 20 ++++++++++----
 backend/app/schemas.py                        |  2 +-
 frontend/src/lib/api/sessions.ts              |  6 ++---
 .../lib/components/sessions/message.svelte    |  2 +-
 frontend/src/lib/types/message.ts             | 10 +++----
 frontend/src/lib/types/session.ts             | 27 ++++++++++++-------
 7 files changed, 51 insertions(+), 30 deletions(-)

diff --git a/backend/app/crud.py b/backend/app/crud.py
index 1e92bcb2..809c6f79 100644
--- a/backend/app/crud.py
+++ b/backend/app/crud.py
@@ -192,18 +192,18 @@ def create_message_metadata(
     return db_message_metadata
 
 
-def create_message_spellcheck(
+def create_message_feedback(
     db: Session,
     message_id: int,
     message: str,
-    spellcheck: schemas.MessageSpellCheckCreate,
-):
+    feedback: schemas.MessageFeedbackCreate,
+) -> str:
     message = (
-        message[: spellcheck.start]
+        message[: feedback.start]
         + "¤µ"
-        + message[spellcheck.start : spellcheck.end]
+        + message[feedback.start : feedback.end]
         + "µ¤"
-        + message[spellcheck.end :]
+        + message[feedback.end :]
     )
 
     db.query(models.Message).filter(models.Message.id == message_id).update(
@@ -211,6 +211,8 @@ def create_message_spellcheck(
     )
     db.commit()
 
+    return message
+
 
 def create_test_typing(db: Session, test: schemas.TestTypingCreate, user: schemas.User):
     db_test = models.TestTyping(user_id=user.id)
diff --git a/backend/app/main.py b/backend/app/main.py
index 9c7f18d0..3e82944e 100644
--- a/backend/app/main.py
+++ b/backend/app/main.py
@@ -613,13 +613,14 @@ def create_message(
 
 
 @sessionsRouter.post(
-    "/{session_id}/messages/{message_id}/spellcheck",
+    "/{session_id}/messages/{message_id}/feedback",
     status_code=status.HTTP_204_NO_CONTENT,
 )
-def spellcheck_message(
+def feedback_message(
     session_id: int,
     message_id: int,
-    spellcheck: schemas.MessageSpellCheckCreate,
+    feedback: schemas.MessageFeedbackCreate,
+    background_tasks: BackgroundTasks,
     db: Session = Depends(get_db),
     current_user: schemas.User = Depends(get_jwt_user),
 ):
@@ -633,14 +634,23 @@ def spellcheck_message(
     ):
         raise HTTPException(
             status_code=401,
-            detail="You do not have permission to spellcheck a message in this session",
+            detail="You do not have permission to feedback this message in this session",
         )
 
     message = crud.get_message(db, message_id)
     if message is None:
         raise HTTPException(status_code=404, detail="Message not found")
 
-    crud.create_message_spellcheck(db, message_id, message.content, spellcheck)
+    new_message = crud.create_message_feedback(db, message_id, message.content, feedback)
+
+    message.content = new_message
+
+    background_tasks.add_task(
+        send_websoket_message,
+        session_id,
+        schemas.Message.model_validate(message),
+        'update',
+    )
 
 
 async def send_websoket_typing(session_id: int, user_id: int):
diff --git a/backend/app/schemas.py b/backend/app/schemas.py
index f5725ed2..a1ca6eb2 100644
--- a/backend/app/schemas.py
+++ b/backend/app/schemas.py
@@ -128,7 +128,7 @@ class MessageCreate(BaseModel):
         from_attributes = True
 
 
-class MessageSpellCheckCreate(BaseModel):
+class MessageFeedbackCreate(BaseModel):
     start: int
     end: int
 
diff --git a/frontend/src/lib/api/sessions.ts b/frontend/src/lib/api/sessions.ts
index c62ad1eb..039f7789 100644
--- a/frontend/src/lib/api/sessions.ts
+++ b/frontend/src/lib/api/sessions.ts
@@ -75,18 +75,18 @@ export async function updateMessageAPI(
 	return response.data;
 }
 
-export async function addMessageSpellCheckAPI(
+export async function addMessageFeedbackAPI(
 	id: number,
 	message_id: number,
 	start: number,
 	end: number
 ): Promise<boolean> {
-	const response = await axiosInstance.post(`/sessions/${id}/messages/${message_id}/spellcheck`, {
+	const response = await axiosInstance.post(`/sessions/${id}/messages/${message_id}/feedback`, {
 		start,
 		end
 	});
 	if (response.status !== 204) {
-		toastAlert('Failed to add spellcheck');
+		toastAlert('Failed to add feedback');
 		return false;
 	}
 	return true;
diff --git a/frontend/src/lib/components/sessions/message.svelte b/frontend/src/lib/components/sessions/message.svelte
index f056d145..761fe2c0 100644
--- a/frontend/src/lib/components/sessions/message.svelte
+++ b/frontend/src/lib/components/sessions/message.svelte
@@ -126,7 +126,7 @@
 		const end = range.end;
 		console.log(start, end);
 
-		const res = await message.addSpellCheck(start, end);
+		const res = await message.addFeedback(start, end);
 
 		if (res) {
 			selection.removeAllRanges();
diff --git a/frontend/src/lib/types/message.ts b/frontend/src/lib/types/message.ts
index 87acfd30..35f00f6c 100644
--- a/frontend/src/lib/types/message.ts
+++ b/frontend/src/lib/types/message.ts
@@ -1,6 +1,6 @@
 import Session from './session';
 import User from './user';
-import { updateMessageAPI, addMessageSpellCheckAPI } from '$lib/api/sessions';
+import { updateMessageAPI, addMessageFeedbackAPI } from '$lib/api/sessions';
 import { toastAlert } from '$lib/utils/toasts';
 import { writable, type Writable } from 'svelte/store';
 
@@ -74,14 +74,14 @@ export default class Message {
 		return true;
 	}
 
-	async localUpdate(content: string): Promise<boolean> {
+	async localUpdate(content: string, force: boolean = false): Promise<boolean> {
 		this._content = content;
-		this._edited = true;
+		if (!force) this._edited = true;
 
 		return true;
 	}
 
-	async addSpellCheck(start: number, end: number): Promise<boolean> {
+	async addFeedback(start: number, end: number): Promise<boolean> {
 		for (let i = 0; i < start + 1; i++) {
 			if (this._content[i] == '¤' || this._content[i] == 'µ') {
 				start++;
@@ -89,7 +89,7 @@ export default class Message {
 			}
 		}
 
-		const response = await addMessageSpellCheckAPI(this._session.id, this._id, start, end);
+		const response = await addMessageFeedbackAPI(this._session.id, this._id, start, end);
 
 		if (!response) return false;
 
diff --git a/frontend/src/lib/types/session.ts b/frontend/src/lib/types/session.ts
index 828ac239..9051f7c2 100644
--- a/frontend/src/lib/types/session.ts
+++ b/frontend/src/lib/types/session.ts
@@ -263,15 +263,24 @@ export default class Session {
 					}
 				} else if (data['action'] === 'update') {
 					const message = Message.parse(data['data']);
-					if (message && !get(this._messages).find((m) => m.id === message.id)) {
-						this._messages.update((messages) => {
-							const mEdited = messages.find((m) => m.message_id === message.message_id);
-							if (!mEdited) return messages;
-							mEdited.localUpdate(message.content);
-							return messages.map((m) => (m.message_id === message.message_id ? mEdited : m));
-						});
-
-						return;
+					if (message) {
+						if (get(this._messages).find((m) => m.id === message.id)) {
+							this._messages.update((messages) => {
+								const mEdited = messages.find((m) => m.id === message.id);
+								if (!mEdited) return messages;
+								mEdited.localUpdate(message.content, true);
+								return messages.map((m) => (m.id === message.id ? mEdited : m));
+							});
+						} else {
+							this._messages.update((messages) => {
+								const mEdited = messages.find((m) => m.message_id === message.message_id);
+								if (!mEdited) return messages;
+								mEdited.localUpdate(message.content);
+								return messages.map((m) => (m.message_id === message.message_id ? mEdited : m));
+							});
+
+							return;
+						}
 					}
 				} else if (data['action'] == 'typing') {
 					this._lastTyping.set(new Date());
-- 
GitLab