mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Clean up code
This commit is contained in:
+42
-13
@@ -4,20 +4,49 @@ alwaysApply: true
|
|||||||
|
|
||||||
When working with this project, follow these rules:
|
When working with this project, follow these rules:
|
||||||
|
|
||||||
|
## Core Behavior
|
||||||
- NEVER do anything i didn't ask you for!
|
- NEVER do anything i didn't ask you for!
|
||||||
- Use double quotes ("") for strings.
|
- Don't talk like a robot. Behave more like a human.
|
||||||
- Do NOT "test the implementation" when you are done. The only exception is when you
|
- Be concise and direct in responses.
|
||||||
need to typecheck or build the app, in that case:
|
- If you're unsure about something, ask for clarification instead of guessing.
|
||||||
|
|
||||||
- To typecheck, run `npm run frontend:typecheck`.
|
## Code Quality & Principles
|
||||||
- To build, run `npm run frontend:build`.
|
|
||||||
|
|
||||||
Do NOT execute other commands like "cd".
|
|
||||||
- Do NOT "cd" to the project directory.
|
|
||||||
- If possible, try to update files in a single edit.
|
|
||||||
- When you need a delay, use `await delay(millis);` in an async function. If the current function is not async,
|
|
||||||
make it async. The import is `<project>/frontend/src/utils/utils`.
|
|
||||||
- When you complete your task, remove unused imports if there are any.
|
|
||||||
- Follow DRY, SOLID, YAGNI and KISS principles.
|
- Follow DRY, SOLID, YAGNI and KISS principles.
|
||||||
- Do NOT use old, outdated or deprecated APIs and functions.
|
- Do NOT use old, outdated or deprecated APIs and functions.
|
||||||
- Don't talk like a robot. Behave more like a human.
|
- Use double quotes ("") for strings consistently.
|
||||||
|
- Prefer functional components over class components in React.
|
||||||
|
- Use TypeScript strictly - avoid `any` types unless absolutely necessary.
|
||||||
|
|
||||||
|
## File Operations
|
||||||
|
- If possible, try to update files in a single edit when making multiple changes.
|
||||||
|
- Do NOT "cd" to the project directory.å
|
||||||
|
|
||||||
|
## Testing & Validation
|
||||||
|
- Do NOT "test the implementation" when you are done. The only exception is when you
|
||||||
|
need to typecheck or build the app, in that case:
|
||||||
|
- To typecheck, run `npm run frontend:typecheck`.
|
||||||
|
- To build, run `npm run frontend:build`.
|
||||||
|
- Do NOT execute other commands like "cd".
|
||||||
|
- If the typecheck passed, there's no need for checking the linter errors.
|
||||||
|
|
||||||
|
## Async Operations
|
||||||
|
- When you need a delay, use `await delay(millis);` in an async function. If the current function is not async,
|
||||||
|
make it async.
|
||||||
|
|
||||||
|
## Database
|
||||||
|
- NEVER create database migrations, they are auto-generated.
|
||||||
|
|
||||||
|
## Project Structure Awareness
|
||||||
|
- This is a React/TypeScript frontend with Python FastAPI backend
|
||||||
|
- Uses MDUI components for UI
|
||||||
|
- Has Electron support for desktop app
|
||||||
|
- Uses Zustand for state management
|
||||||
|
- Uses use-immer for immutable state updates
|
||||||
|
- Uses React Router for navigation
|
||||||
|
- Has WebSocket support for real-time features
|
||||||
|
- Uses encryption (tweetnacl) for security
|
||||||
|
|
||||||
|
## Performance & Efficiency
|
||||||
|
- Batch tool calls when possible to reduce latency
|
||||||
|
- Use semantic search before grep when looking for concepts
|
||||||
|
- Use TODOs for complex multi-step tasks to track progress
|
||||||
|
|||||||
+1
-1
@@ -120,7 +120,7 @@ class RegisterRequest(BaseModel):
|
|||||||
|
|
||||||
class SendMessageRequest(BaseModel):
|
class SendMessageRequest(BaseModel):
|
||||||
content: str
|
content: str
|
||||||
reply_to_id: int | None
|
reply_to_id: int | None = None
|
||||||
|
|
||||||
|
|
||||||
class EditMessageRequest(BaseModel):
|
class EditMessageRequest(BaseModel):
|
||||||
|
|||||||
@@ -90,20 +90,6 @@ export function ChatMessages({ messages = [], children, isDm = false, onReplySel
|
|||||||
if (!toBeDeleted || !user.authToken) return;
|
if (!toBeDeleted || !user.authToken) return;
|
||||||
try {
|
try {
|
||||||
onDelete?.(toBeDeleted.id);
|
onDelete?.(toBeDeleted.id);
|
||||||
// if (toBeDeleted.isDm) {
|
|
||||||
// // For DM, send dmDelete
|
|
||||||
// await request({
|
|
||||||
// type: "dmDelete",
|
|
||||||
// data: { id: toBeDeleted.id },
|
|
||||||
// credentials: { scheme: "Bearer", credentials: user.authToken }
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// await request({
|
|
||||||
// type: "deleteMessage",
|
|
||||||
// data: { message_id: toBeDeleted.id },
|
|
||||||
// credentials: { scheme: "Bearer", credentials: user.authToken }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to delete message:", error);
|
console.error("Failed to delete message:", error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ export function RichTextArea({
|
|||||||
const hiddenTextareaRef = useRef<HTMLTextAreaElement | null>(null);
|
const hiddenTextareaRef = useRef<HTMLTextAreaElement | null>(null);
|
||||||
const heightRef = useRef<number | null>(null);
|
const heightRef = useRef<number | null>(null);
|
||||||
|
|
||||||
const getStyleValue = (computedStyle: CSSStyleDeclaration, prop: keyof CSSStyleDeclaration): number => {
|
function getStyleValue(computedStyle: CSSStyleDeclaration, prop: keyof CSSStyleDeclaration): number {
|
||||||
const raw = (computedStyle as any)[prop] as string | number | undefined;
|
const raw = computedStyle[prop] as string | number | undefined;
|
||||||
if (raw == null) return 0;
|
if (raw == null) return 0;
|
||||||
const str = String(raw);
|
const str = String(raw);
|
||||||
return str.endsWith("px") ? parseFloat(str) : parseFloat(str) || 0;
|
return str.endsWith("px") ? parseFloat(str) : parseFloat(str) || 0;
|
||||||
};
|
}
|
||||||
|
|
||||||
const calculateTextareaStyles = useCallback(() => {
|
const calculateTextareaStyles = useCallback(() => {
|
||||||
const textarea = textareaRef.current;
|
const textarea = textareaRef.current;
|
||||||
@@ -116,9 +116,7 @@ export function RichTextArea({
|
|||||||
textarea.style.overflowY = overflowing ? "hidden" : "";
|
textarea.style.overflowY = overflowing ? "hidden" : "";
|
||||||
}, [calculateTextareaStyles]);
|
}, [calculateTextareaStyles]);
|
||||||
|
|
||||||
const useEnhancedEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
|
useLayoutEffect(() => {
|
||||||
|
|
||||||
useEnhancedEffect(() => {
|
|
||||||
syncHeight();
|
syncHeight();
|
||||||
}, [syncHeight, text]);
|
}, [syncHeight, text]);
|
||||||
|
|
||||||
@@ -142,13 +140,13 @@ export function RichTextArea({
|
|||||||
};
|
};
|
||||||
}, [syncHeight]);
|
}, [syncHeight]);
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
function handleChange(e: React.ChangeEvent<HTMLTextAreaElement>) {
|
||||||
// Keep height responsive during rapid uncontrolled input bursts
|
// Keep height responsive during rapid uncontrolled input bursts
|
||||||
syncHeight();
|
syncHeight();
|
||||||
onTextChange(e.target.value);
|
onTextChange(e.target.value);
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
|
||||||
const isCtrlEnter = e.key === "Enter" && (e.ctrlKey || e.metaKey);
|
const isCtrlEnter = e.key === "Enter" && (e.ctrlKey || e.metaKey);
|
||||||
const isPlainEnter = e.key === "Enter" && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey;
|
const isPlainEnter = e.key === "Enter" && !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey;
|
||||||
|
|
||||||
@@ -175,7 +173,7 @@ export function RichTextArea({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user