main f6d8405

message.ts RawHistoryFolder

1import { z } from 'zod';
2
3// Message constraints
4export const MAX_MESSAGE_LENGTH = 500;
5export const MIN_MESSAGE_LENGTH = 1;
6// Visitors see this many latest messages of the default room before the registration prompt.
7// Keep in sync with PUBLIC_MESSAGE_LIMIT in src/convex/queries.ts.
8export const PUBLIC_PREVIEW_MESSAGES = 50;
9
10// Message content schema
11export const messageContentSchema = z
12	.string()
13	.min(MIN_MESSAGE_LENGTH, 'Message cannot be empty')
14	.max(MAX_MESSAGE_LENGTH, `Message cannot exceed ${MAX_MESSAGE_LENGTH} characters`)
15	.trim();
16
17// Full send message request schema
18// Note: ID format validation is relaxed - DB queries validate existence
19export const sendMessageSchema = z.object({
20	content: messageContentSchema,
21	userId: z.string().min(1, 'User ID is required'),
22	chatRoomId: z.string().min(1).optional(),
23	type: z.enum(['chat', 'emote', 'system']).default('chat'),
24	styleData: z.unknown().optional()
25});
26
27export type SendMessageInput = z.infer<typeof sendMessageSchema>;
28
29// Validation helper function
30export function validateMessageContent(content: string): {
31	isValid: boolean;
32	error?: string;
33	sanitized: string;
34} {
35	const result = messageContentSchema.safeParse(content);
36
37	if (result.success) {
38		return {
39			isValid: true,
40			sanitized: result.data
41		};
42	}
43
44	return {
45		isValid: false,
46		error: result.error.issues[0]?.message || 'Invalid message',
47		sanitized: content.slice(0, MAX_MESSAGE_LENGTH).trim()
48	};
49}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 8

↑↓ moveenter openesc close